[자바]파일에서 BOM 문자 제거하기

2022. 4. 10. 22:34프로그래밍

728x90

https://www.rgagnon.com/javadetails/java-handle-utf8-file-with-bom.html

 

Real's How-to

Real's HowTo : Useful code snippets for Java, JS, PB and more

www.rgagnon.com

 

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;
}

 

테스트는 다음과 같이 텍스트 파일을 하나 만들어서 진행해 봅시다.

 

728x90