在C++中处理非ASCII字符

4

我在 C++ 中遇到了一些非 ASCII 字符的问题。我有一个包含非 ASCII 字符的文件,我通过文件处理在 C++ 中读取它。在读取文件(假设为 1.txt)后,我将数据存储到字符串流中,并将其写入另一个文件(假设为 2.txt)。

假设 1.txt 包含:

ação

在2.txt中,我应该得到相同的输出,但非ASCII字符会以它们的十六进制值打印在2.txt中。
另外,我很确定C++仅将ASCII字符处理为ASCII。
请帮助正确打印这些字符到2.txt中。
编辑:
首先是整个过程的伪代码:
1.Shell script to Read from DB one Value and stores in 11.txt
2.CPP Code(a.cpp) reading 11.txt and Writing to f.txt

数据库中读取的数据: 安装

文件 11.txt 中包含: Instalação

文件 F.txt 中包含: Instalação

a.cpp 在屏幕上输出的结果: 安装

a.cpp

#include <iterator>
#include <iostream>
#include <algorithm>
#include <sstream>
#include<fstream>
#include <iomanip>

using namespace std;
int main()
{
    ifstream myReadFile;
    ofstream f2;
    myReadFile.open("11.txt");
    f2.open("f2.txt");
    string output;
    if (myReadFile.is_open()) 
    {
        while (!myReadFile.eof())
        {
            myReadFile >> output;
                //cout<<output;

            cout<<"\n";

            std::stringstream tempDummyLineItem;
            tempDummyLineItem <<output;
            cout<<tempDummyLineItem.str();
            f2<<tempDummyLineItem.str();
        }
    }
    myReadFile.close();
    return 0;
}

Locale的含义是:

LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

那么你的问题是什么?“如何识别ASCII字符,并将非ASCII字符打印为十六进制?” - Mats Petersson
请发布您的实际代码(最小的展示问题的样本),然后我们可以告诉您需要进行哪些最小更改。 - chris
我想让非ASCII字符在2.txt中仅以非ASCII形式打印,而不是它们的十六进制值。 - Mayank Jain
2
@MayankJain,发布的代码应该与伪代码长度相同。这种情况下,不可能对此SSCCE进行版权保护。 - chris
抱歉,我并不是很了解这些概念。不过,在Unix中使用file -i命令可以给我提供以下信息:text/plain; charset=iso-8859-1。这个文件是由C++文件处理函数创建的。希望这正是你正在寻找的。 - Mayank Jain
显示剩余10条评论
2个回答

3

如果我理解您的意思,至少我会这样做:

#include <iterator>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <iomanip>

std::string to_hex(char ch) {
    std::ostringstream b;
    b << "\\x" << std::setfill('0') << std::setw(2) << std::setprecision(2)
        << std::hex << static_cast<unsigned int>(ch & 0xff);
    return b.str();
}

int main(){
    // for test purposes, we'll use a stringstream for input
    std::stringstream infile("normal stuff. weird stuff:\x01\xee:back to normal");

    infile << std::noskipws;

    // copy input to output, converting non-ASCII to hex:
    std::transform(std::istream_iterator<char>(infile),
        std::istream_iterator<char>(),
        std::ostream_iterator<std::string>(std::cout),
        [](char ch) {
            return (ch >= ' ') && (ch < 127) ?
                std::string(1, ch) :
                to_hex(ch);
    });
}

0

听起来像是一个 utf8 问题。由于您没有在问题中标记 c++11 这里,这是一篇关于 Unicode 和 C++ 流的优秀文章。

根据您的更新代码,让我解释一下发生了什么。您创建了一个文件流来读取您的文件。在内部,文件流只能识别 chars,除非你告诉它不是。在大多数机器上,char 只能容纳 8 位数据,但是您的文件中的字符使用的位数超过了 8 位。为了能够正确读取您的文件,您需要知道它是如何编码的。最常见的编码是 UTF-8,它使用 1 到 4 个 chars 来表示每个字符。

一旦您知道了您的编码方式,就可以使用 wifstream(用于 UTF-16)或为其他编码方式 imbue() 区域设置。

更新: 如果您的文件是 ISO-88591(来自您上面的评论),请尝试这样做。

wifstream myReadFile;
myReadFile.imbue(std::locale("en_US.iso88591"));
myReadFile.open("11.txt");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接