2012-02-21 6 views
2

ファイルを読み込むと、最初に読み込まれているファイルが3つあります。ファイル内にない文字を読み取るストリーム

はそれらは:「私»¿」

ファイルが含まれています:

<root> 
    <tag> 
    <anothertag>Text</anothertag> 
    </tag> 
    <tag> 
    <anothertag>Text</anothertag> 
    </tag> 
</root> 

マイコード:

//scanner.h 
enum TOKEN_TYPE { 
    OPEN, CLOSE, TEXT 
}; 

struct Token { 
    int type; 
    std::string value; 
}; 

class Scanner { 
public: 
    Scanner(std::string path); 

    void scan(std::string path); 

private: 
    std::vector<Token> tokens; 

    Token readToken(std::ifstream& in); 
}; 

std::string read_to(std::istream& in, char delim); 

//scanner.cpp 
Scanner::Scanner(std::string path) { 
    scan(path); 
} 

void Scanner::scan(std::string path) { 
    std::ifstream in(path, std::ios_base::beg); 

    if(!in.is_open()) { 
     return; 
    } 

    if(!tokens.empty()) { 
     tokens.erase(tokens.begin(), tokens.end()); 
    } 

    std::ofstream out("output.txt"); 
    while(!in.eof()) { 
     tokens.push_back(readToken(in)); 

     if(tokens.back().value.empty()) { 
      tokens.pop_back(); 
      continue; 
     } 

     out << tokens.size() << "\t" << tokens.back().value << "\t" << tokens.back().value.length() << std::endl; 
    } 

    in.close(); 

    out << "\n"; 
    for(int i = 0; i < tokens.size(); ++i) { 
     if(tokens[i].type == TOKEN_TYPE::TEXT) { 
      out << tokens[i].value << std::endl; 
     } 
    } 

    out.close(); 
} 

Token Scanner::readToken(std::ifstream& in) { 
    Token token; 

    char c = in.get(); 
    while(c == '\n' || c == '\t' || c == ' ') { 
     c = in.get(); 
    } 

    if(c == '<') { 
     c = in.get(); 

     if(c == '/') { 
      token.type = TOKEN_TYPE::CLOSE; 
      token.value = read_to(in, '>'); 
     } else { 
      in.unget(); 

      token.type = TOKEN_TYPE::OPEN; 
      token.value = read_to(in, '>'); 
     } 
    } else { 
     in.unget(); 

     token.type = TOKEN_TYPE::TEXT; 
     token.value = read_to(in, '<'); 

     in.unget(); 
    } 

    return token; 
} 

inline std::string read_to(std::istream& in, char delim) { 
    std::stringstream str; 

    char c; 
    while((c = in.get()) != delim && in.good()) { 
     str << c; 
    } 

    return str.str(); 
} 


int main(int argc, char** argv) { 
    Scanner scanner("test.xml"); 
    return 0; 
} 

はなぜストリームが実際に存在しないこれらの文字を読んでいます?

+1

これはBOMの問題であるため、この重複するリンクにリンクしています。[C++でバイトオーダーのマークを無視してストリームから読み込む](http://stackoverflow.com/questions/8880548/ignore-byte-order -mark-in-c-reading-a-stream) – Benoit

+0

申し訳ありませんが重複している場合は、今までBOMを認識していなかったので、何を検索するのか分かりませんでした。 – Lerp

+0

@Rarge:ヒント:「」を検索してください。 – ybungalobill

答えて

7

""はUTF-8 BOMです。手動でスキップするか、ファイルから削除する必要があります(UTF-8にはBOMは必要ありません)。

+1

しかし、それをUTF-8(Latin 1とは対照的)として識別することは可能です。特に、「」はUTF-8 BOMではありません。 (UTF-8 BOMはUTF-8でゼロ幅のスペースとして表示されます) –

+1

@JamesKanze:これは*あなた*を区別することはできませんUTF-8とLatin1を使用することができます。UTF-8を認識することができますが、UTF-8でなければLatin1であると推論できません。他にも1バイトのレガシーエンコーディングがたくさんあります。外部ヒントなしでは、それらを確実に区別することはできません。唯一の*正気な方法は、UTF-8 *どこでも*と仮定し、他のすべてのシングルバイトエンコーディングを非難することです。このように、BOMは冗長であり、実際、UnicodeコンソーシアムはBOMに対して推奨しているわけではなく、Windows以外の世界でも一般的ではありません。 – ybungalobill

+0

@ JamesKanze:2枚目のメモについて、「XはY」と「YはX」の違いをご理解ください。 – ybungalobill

関連する問題