https://www.rgagnon.com/javadetails/java-handle-utf8-file-with-bom.html
XML 파일을 파싱하려다 보니 너무 많이 걸리는 것이 이 Byte Order Mark이다.
XML 파서 라이브러리를 사용하면 xml 파싱 전에 이 BOM 때문에 오류를 발생 시키는 것이었다.
아래 표는 가장 일반적으로 사용되는 BOM 내용 입니다.
바이너리 형태를 볼 수 있는 텍스트 편집기에서 열어보면 보이는 말그대로 Byte Order를 식별 해 줄수 있도록 하는 헤더정보인데
웹시스템 특히나 유닉스나 리눅스에서 구동시키는 웹서버 시스템에서 파싱을 하다가 오류를 내는 골치가 아픈 경우가 많아서 BOM 정보가 있는 파일인 경우에는 이 정보를 없애 버리는 프로그램을 만들어 보기로 했습니다.
내용은 일단 위의 BOM이 있으면 파일에서 이 내용을 제거하기 위해서
기존 파일을 새 파일로 읽어 들일때 상기 바이트를 제거 하는 방식으로 코딩을 하였는 데...
파일이 잘 안 지워지는 문제가 발생을 했습니다.
찬찬히 살펴 보아야 겠으나 귀찮아서 나중에 찾기로 해 봅니다.
사용법:
다음과 같이 XML 파일을 라이브러리로 보내기 전에 InputStream 객체를 전달하는 getInputStreamWithoutBOM 메서드를 만드는 것입니다.
public static void main(String[] args)
{
String fileName = "C:\\DEV\\DOCS\\MyBlog\\ATExt.txt";
String fileOutName = "C:\\DEV\\DOCS\\MyBlog\\ATExtOut.txt";
FileOutputStream fOuts = null;
FileChannel fOut = null;
FileChannel fIn = null;
try {
fOuts = new FileOutputStream((new File(fileOutName)));
fOut = fOuts.getChannel();
fIn = getInputStreamWithoutBOM(new File(fileName)).getChannel();
fIn.transferTo(0, fIn.size(), fOut);
} catch (IOException e) {
}
finally
{
try {
fOuts.close();
fOut.close();
fIn.close();
} catch (IOException e) {
}
}
new File(fileName).deleteOnExit();
}
getInputStreamWithoutBOM 메서드의 구현은 다음과 같습니다.
private final InputStream getInputStreamWithoutBOM(final File templatePath)
{
FileInputStream fin = null;
FileOutputStream fout = null;
InputStream result = null;
File fi = null;
File fo = null;
int fSize = -1;
ByteBuffer bbuf = ByteBuffer.allocate(4);
String strFilePath = null;
String strFilePathOrg = null;
try {
fi = templatePath;
strFilePathOrg = templatePath.getAbsolutePath();
strFilePath = templatePath.getAbsolutePath() + ".cpy";
fo = new File(strFilePath);
fin = new FileInputStream(fi);
fout = new FileOutputStream(fo);
FileChannel fchin = fin.getChannel();
fchin.read(bbuf);
fSize = (int) fchin.size();
byte[] bb = bbuf.array();
boolean isOneOfThem = false;
if ((bb[0] & 0x00FF) == 0x3C && (bb[1] & 0x00FF) == 0x3F) {
fin.close();
fchin.close();
fchin = null;
bbuf = null;
fin = null;
return new FileInputStream(strFilePathOrg);
}
FileChannel fchout = fout.getChannel();
if ((bb[0] & 0x00FF) == 0xEF && (bb[1] & 0x00FF) == 0xBB && (bb[2] & 0x00FF) == 0xBF) // UTF-8
{
fchin.transferTo(3, fSize - 3, fchout);
isOneOfThem = true;
fchin.close();
fchout.close();
fin.close();
fout.close();
fchin = null;
fchout = null;
fin = null;
fout = null;
}
if ((bb[0] & 0x00FF) == 0xFE && (bb[1] & 0x00FF) == 0xFF) // UTF-16(BE)
{
fchin.transferTo(2, fSize - 2, fchout);
isOneOfThem = true;
fchin.close();
fchout.close();
fin.close();
fout.close();
fchin = null;
fchout = null;
fin = null;
fout = null;
}
if ((bb[0] & 0x00FF) == 0xFF && (bb[1] & 0x00FF) == 0xFE) // UTF-16(LE)
{
fchin.transferTo(2, fSize - 2, fchout);
isOneOfThem = true;
fchin.close();
fchout.close();
fin.close();
fout.close();
fchin = null;
fchout = null;
fin = null;
fout = null;
}
if ((bb[0] & 0x00FF) == 0x00 && (bb[1] & 0x00FF) == 0x00 && (bb[2] & 0x00FF) == 0xFE
&& (bb[3] & 0x00FF) == 0xFF) // UTF-32(BE)
{
fchin.transferTo(4, fSize - 4, fchout);
isOneOfThem = true;
fchin.close();
fchout.close();
fin.close();
fout.close();
fchin = null;
fchout = null;
fin = null;
fout = null;
}
if ((bb[0] & 0x00FF) == 0xFF && (bb[1] & 0x00FF) == 0xFE && (bb[2] & 0x00FF) == 0x00
&& (bb[3] & 0x00FF) == 0x00) // UTF-32(LE)
{
fchin.transferTo(4, fSize - 4, fchout);
isOneOfThem = true;
fchin.close();
fchout.close();
fin.close();
fout.close();
fchin = null;
fchout = null;
fin = null;
fout = null;
}
if (isOneOfThem) {
if (fi.delete()) {
fi = new File(strFilePath);
fo = new File(strFilePathOrg);
fin = new FileInputStream(fi);
fout = new FileOutputStream(fo);
fchin = fin.getChannel();
fchout = fout.getChannel();
fSize = (int) fchin.size();
fchin.transferTo(0, fSize, fchout);
fchin.close();
fchout.close();
fin.close();
fout.close();
fchin = null;
fchout = null;
fin = null;
fout = null;
fi.delete();
result = new FileInputStream(fo);
}
}
} catch (IOException ie) {
ie.printStackTrace();
}
return result;
}
테스트는 다음과 같이 텍스트 파일을 하나 만들어서 진행해 봅시다.
'프로그래밍' 카테고리의 다른 글
자바, C++ enum (0) | 2022.04.10 |
---|---|
[C#] 바이너리 파일 표시기 만들기 - ByteViewer 클래스 (0) | 2022.04.10 |
Win32 어셈블리 프로그래밍 - 4. 텍스트 그리기 (0) | 2022.04.04 |
Win32 어셈블리 프로그래밍 - 3. 간단한 윈도우 (0) | 2022.04.04 |
Win32 어셈블리 프로그래밍 - 2. 메시지 박스 (0) | 2022.04.04 |