2012-02-21 2 views
2

파일을 읽을 때 먼저 파일에없는 세 문자가 읽혀지고 있습니다.파일에없는 문자 읽기 스트림

는 그들은 : ""

파일이 포함되어

<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이 아닙니다. 라틴어 1 인 것처럼 UTF-8 BOM의 바이트가 표시됩니다 (UTF-8 BOM은 UTF-8로 너비가 0 인 공백으로 표시됩니다). –

+1

@JamesKanze : 사용자가 구별 할 수 없도록합니다. UTF-8 및 라틴어 1. UTF-8을 인식 할 수 있지만 UTF-8이 아니면 라틴어 1을 추론 할 수 없습니다. 다른 1 바이트 레거시 인코딩이 많이 있습니다. 외부 힌트 없이는 이들을 확실하게 구별 할 수 없습니다. 유일하게 * 제정신 인 방법은 UTF-8 * 모든 곳에서 * 사용하고 다른 모든 싱글 바이트 인코딩을 사용하지 않는 것입니다. 이 방법은 BOM이 중복되고, 실제로 유니 코드 컨소시엄은 BOM을 권장하지 않으며 비 Windows 환경에서도 일반적으로 사용하지 않습니다. – ybungalobill

+0

@ JamesKanze : 두 번째 메모와 관련하여 "X is Y"와 "Y is X"의 차이점을 이해하십시오. – ybungalobill