FileInputStream을 이용해 Bitmap File Size 출력하기
File - new - class
class명을 Program 으로 넣고
Package에 ex1을 넣어 패키지와 클래스를 동시에 생성 한다.
구글에서 '풍경사진'을 검색후 bmp파일로 저장한다.
작업하고있는 프로젝트폴더 안에 'res'폴더를 만들고 사진파일을 넣어준다.
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가 비트맵파일 속성의 내용과 같은지 확인한다.
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();
}
}
오류발생
- 값이 음수로 나온 경우
- 비트맵 파일 속성과 다른 숫자가 나온 경우
값이 음수로 나온경우 :
합집합시 다른 비트가 섞여서 발생할 수있다.
쉬프트연산 전에 b4에 0x000000ff를 비트연산자&를 사용해서 총 32비트중 의도했던 비트만 나오게한다.
비트맵 파일 속성과 다른 숫자가 나온 경우:
비트맵파일 구조상 맨앞 2바이트는 시그니처이므로 그 뒤의 4바이트를 출력해야 filesize를 출력할 수있다.
시그니처부분을 담을 read()메소드를 생략한 경우 다른숫자가 출력되었다.
read()출력부분을 버리지않았다면
Signature 2바이트 + FileSize 2바이트가 출력된것.
'2021 Newlecture > JAVA' 카테고리의 다른 글
nextInt() , nextLine()사용시 주의사항/Integer.pasrseInt() (0) | 2021.03.08 |
---|---|
복합 대입연산자 / 삼항연산자 (0) | 2021.03.08 |
제어구조 / FileStream을 통해 파일복사 (0) | 2021.03.05 |
쉬프트연산 / 진법 / 0x000000ff과 교집합 (0) | 2021.03.05 |
산술연산/ 단항,비교논리,비트,쉬프트 연산자/ FileStream이용한 메모장 입력출력 (0) | 2021.03.03 |
System.in.read() / Scanner / next() / 메모장내용 출력하기 (0) | 2021.03.02 |
이스케이프문자, 포멧문자열, 형식지정자, print()함수 (0) | 2021.02.26 |
개체와 객체 / 아스키코드/ 이클립스설치/System.out.println() (0) | 2021.02.25 |