FileInputStream을 이용해 Bitmap File Size 출력하기

 

더보기

File - new - class 

class명을 Program 으로 넣고

Package에 ex1을 넣어 패키지클래스를 동시에 생성 한다.

구글에서 '풍경사진'을 검색후 bmp파일로 저장한다.

작업하고있는 프로젝트폴더 안에 'res'폴더를 만들고 사진파일을 넣어준다.

 

res폴더 생성 후 bmp파일 넣은 화면

FileInputStream("절대경로")를 상대경로로 바꿔준다.

FileInputStream fis = new FileInputStream("res/aaa.bmp");

절대경로는 다른컴퓨터로 가져가겼을때 소스코드가 변경되어야하는 불편함이생긴다.

소스코드의 위치는 bin폴더에있지만, project파일위치 기준으로 상대경로를잡는다.

 

 

 

FileInputStream fis = new FileInputStream("res/aaa.bmp");

  • 입력스트림에 bmp파일의 상대경로를 넣어준다.

int b ;

b = fis.read();

b = fis.read();

  • FileInputStream의 객체 fis를 이용해서 이미지파일의 크기를 읽어온다.
  • read()는 호출될때마다 1바이트씩 불러온다.
  • 비트맵파일의 구조는 Signature, FileSize, Reserved,FileOffset순이며 Signature(비트맵을 상징하는자리)는 2바이트(1바이트씩 2자리)를 차지한다.

int b1 = fis.read();

int b2 = fis.read();

int b3 = fis.read();

int b4 = fis.read();

  • 파일사이즈를 읽어오기위한 변수선언을 새로 해준다.
  • 파일사이즈는 4바이트이므로 변수 4개를 선언하고 fis객체를 이용해 순서대로 초기화시킨다.
  • 앞서 b에 Signature 2바이트를 불렀고, 다음 FileSize를 위해 변수4개를 새로 만들고 read()를 4번호출한다.
  • 비트맵파일의 구조에서 FileSize(파일의 크기)는 Signature다음의 4자리(4바이트)에 나타난다. 변수b에 담긴건 버린다.

int fileSize = 0;

  • read()로 불러온 파일사이즈(b1~b4)를 담을 변수 fileSize를 선언해주고 0으로 초기화한다.
  • int로 4바이트가 담긴다.

fileSize = (b4 & 0x000000ff) << 8*3 |

             (b3 & 0x000000ff) << 8*2 |

             (b2 & 0x000000ff) << 8*1 |

             (b1 & 0x000000ff);

  • 파일에 저장되어있는 바이트순서(Big Endian)와 CPU(Little Endian)의 바이트출력순서가 다르기때문에 쉬프트연산(*)을 통해 위치변동을 한다.
  • 0x000000ff(*)와 비트연산자' & '(교집합) 이용하면 원하는 위치에 담을 수 있다.
  • 비트연산자 ' | '(합집합)을해서 불러온 비트를 합치고 fileSize에 대입한다.

System.out.println(Integer.toBinaryString(b4));

System.out.println(Integer.toBinaryString(b3));

System.out.println(Integer.toBinaryString(b2));

System.out.println(Integer.toBinaryString(b1));

  • b1부터 b4의 정수값을 2진수로 출력하기
  • Integer.toBinaryString()은 정수를 2진수로 변환하는 메소드

System.out.printf("file size : %d\n",fileSize);

  • println메소드를 통해 콘솔에 출력한다
  • fileSize가 비트맵파일 속성의 내용과 같은지 확인한다.

콘솔화면  /  bmp파일 속성

package ex1.bit;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;

public class Program {

	public static void main(String[] args) throws IOException {
		// 1. 이미지파일을 일기위한 파일입력 스트림을 fis로 생성
		FileInputStream fis = new FileInputStream("res/aaa.bmp");
		
		// 이미지 파일의 Signature를 불러온 후 FileSize를 불러온다.
		int b;
		// 2바이트
		b = fis.read();
		b = fis.read();
		
		//fileSize
		int b1 = fis.read();
		int b2 = fis.read();
		int b3 = fis.read();
		int b4 = fis.read();
		
		//b1b2b3b4		
		int fileSize = 0; //[b1][b2][b3][b4];
		fileSize = b1;// [][][][b1]; 자체가 32비트
		fileSize = b2;// [][][][b2];
		fileSize = b3;// [][][][b3];
		fileSize = b4;// [][][][b4];
		
		fileSize = (b4 & 0x000000ff) << 8*3 | //[b4][][][] 원래는 오른쪽부터채워지는데,왼쪽으로옮김
			(b3 & 0x000000ff) << 8*2 | //[b4][b3][][]
			(b2 & 0x000000ff) << 8*1 | //[b4][b3][b2][]
			(b1 & 0x000000ff);         //[b4][b3][b2][b1]
					
		System.out.println(Integer.toBinaryString(b4)); // 변수별로 바이너리값출력
		System.out.println(Integer.toBinaryString(b3));
		System.out.println(Integer.toBinaryString(b2));
		System.out.println(Integer.toBinaryString(b1));
	
		System.out.printf("file size : %d\n",fileSize);
		fis.close();
	}

}

오류발생

  1.  값이 음수로 나온 경우
  2.  비트맵 파일 속성과 다른 숫자가 나온 경우

값이 음수로 나온경우 :

합집합시 다른 비트가 섞여서 발생할 수있다.

쉬프트연산 전에 b4에 0x000000ff를 비트연산자&를 사용해서 총 32비트중 의도했던 비트만 나오게한다.

쉬프트연산 / 진법 / 0x000000ff과 교집합

비트맵 파일 속성과 다른 숫자가 나온 경우:

비트맵파일 구조상 맨앞 2바이트는 시그니처이므로 그 뒤의 4바이트를 출력해야 filesize를 출력할 수있다.

시그니처부분을 담을 read()메소드를 생략한 경우 다른숫자가 출력되었다.

read()출력부분을 버리지않았다면

Signature 2바이트 + FileSize 2바이트가 출력된것. 

+ Recent posts