** Byte Order Mark에 대해서는 따로 다루지 않습니다.

https://www.w3.org/International/questions/qa-byte-order-mark

 

최근 UTF-8 BOM 때문에 골치가 좀 아팠습니다.

org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; 프롤로그에서는 콘텐츠가 허용되지 않습니다.
  at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:257)
  at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339)

이런 코드였구요.

InputSource inputSource = new InputSource(new StringReader(c));
inputSource.setEncoding("UTF-8");
 
doc = builder.parse(inputSource);

일반적인 상황에서는 잘 되었는데 BOM이 포함된 UTF-8에서 문제가 있었습니다.

 

stackoverflow에 이런 문제로 어려움을 겪는 사람이 많이 있었고 답변도 다양했는데 딱 입맛에 맞는 답변을 찾기는 어렵더군요. 대부분 툴을 써서 BOM을 제거해라, 혹은 awk를 사용해라 등등..

그러다가 꽤 마음에 드는 포스팅을 찾았구요.

http://stackoverflow.com/questions/1835430/byte-order-mark-screws-up-file-reading-in-java

Git의 https://github.com/gpakosz/UnicodeBOMInputStream 와 동일합니다.

 

아무튼 이렇게 수정을 했습니다.

InputStream inputStream = new ByteArrayInputStream(c.getBytes());
UnicodeBOMInputStream cleanInputStream = new UnicodeBOMInputStream(inputStream);
cleanInputStream.skipBOM();
 
doc = builder.parse(cleanInputStream);

그리고 잘 됩니다!

 

이후에 잘 되다가 유독 Windows에서만 "Problem with a document: Invalid byte 3 of 3-byte UTF-8 sequence"에러가 났는데요, 이 때는 -Dfile.encoding=UTF-8 속성 추가하고 잘 해결했습니다.