본문 바로가기

old drawer/Java

java 파일 입출력

1. 접두.접미어만 알면 반은 먹고 들어간다!!
스트림 읽기 쓰기
바이트 InputStream OutputStream
문 자 Reader Writer

파일 'File-' / 버퍼 'Buffered-' / 자료형, String Class 'Data-'

ex 1) 파일을 문자 단위로 읽기 위한 클래스는?
파일 File, 문자 읽기 Reader → FileReader
ex 2) 바이트 데이터를 문자 단위로 저장 하고 싶다면?
바이트 쓰기 OutputStream -> 문자 쓰기 Writer → OutputStreamWriter

2. 클래스 구조 및 설명(byte stream)
모든 상위 클래스의 메서드는 하위 클래스에 상속 된다!
        는 Pass!!
[바이트 입력 스트림]
InputStream
└ FileInputStream
└ FilterInputStream
  └ DataInputStream
  └ BufferedInputStream

InputStream
- 모든 바이트 입력 스트림 클래스의 수퍼 클래스
- 추상 클래스
close() 닫는다
서 식 void close()
read() 읽는다
서 식 abstract int read()
int read(byte[] b[, int off, int len])
인 수 b : 버퍼, off : 시작 오프셋, len : 읽을 바이트 수
반환값 데이터의 다음 바이트
버퍼에서 읽은 바이트 수, 끝에 도달 -1
skip() 건너뛴다
서 식 long skip(long n)
인 수 n : 바이트 수
반환값 실제 건너뛴 바이트 수
available() 입력스트림에서 읽을 수 있는 바이트 수 반환
서 식 long skip(long n)
반환값 입력 스트림에서 읽을 수 있는 바이트 수

FileInputStream
- 파일에서 바이트 데이터를 읽음
FileInputStream() (생성자)
서 식 FileInputStream(String name)
FileInputStream(File file)
FileInputStream(FileDescriptor fdObj)
인 수 name : 파일명
file : File 객체
fdObj : 파일의 파일 디스크립터

FilterInputStream
- 데이터를 변환, 조작할수 있게 InputStream 에서 확장

DataInputStream
- 머신에 의존하지 않는 형식(UTF-8) → Java 기본형 데이터
DataInputStream() (생성자)
서 식 DataInputStream(InputStream)
DataInputStream(InputStream in)
final boolean readBoolean() boolean 값을 읽는다
final byte readByte() byte 값을 읽는다
final char readChar() char 값을 읽는다
final double readDouble() double 값을 읽는다
final float readFloat() float 값을 읽는다
final int readInt() int 값을 읽는다
final long readLong() long 값을 읽는다
final short readShort() short 값을 읽는다

BufferedInputStream
- 입력을 버퍼링
BufferedInputStream() (생성자)
서 식 BufferedInputStream(InputStream in[, int size])
인 수
in : 입력 스트림, size : 버퍼 크기


[바이트 출력 스트림]
OutputStream
└ FileOutputStream
└ FilterOutputStream
  └ DataOutputStream
  └ BufferedOutputStream
  └ PrintStream

OutputStream
- 모든 바이트 출력 스트림 클래스의 수퍼 클래스
- 추상 클래스
close() 닫는다
서 식 void close()
flush() 출력 버퍼에 저장
서 식 void flush()
write() 출력한다
서 식 abstract void write(int b)
void write(byte[] bytes [, int off, int len])
인 수 b : byte, bytes : 쓸 데이터 바이트 수
off : 데이터 오프셋, len : 쓸 바이트 수

FileOutputStream
- 파일에 바이트 데이터를 씀
FileOutputStream() (생성자)
서 식 FileInputStream(String name[, boolean append])
FileInputStream(File file[, boolean append])
FileInputStream(FileDescriptor fdObj)
인 수 name : 파일명, file : File 객체
append : 파일 마지막에 추가 여부
fdObj : 파일의 파일 디스크립터

FilterOutputStream
- 데이터를 변환, 조작할수 있게 OutputStream 에서 확장

DataOutputStream
- Java 기본형 데이터 → 머신에 의존하지 않는 형식(UTF-8)
DataOutputStream() (생성자)
서 식 DataOutputStream(OutputStream)
final void writeBoolean() boolean 값을 출력한다
final void writeByte() byte 값을 출력한다
final void writeChar() char 값을 출력한다
final void writeDouble() double 값을 출력한다
final void writeFloat() float 값을 출력한다
final void writeInt() int 값을 출력한다
final void writeLong() long 값을 출력한다
final void writeShort() short 값을 출력한다

BufferedOutputStream
- 출력을 버퍼링
BufferedOutputStream() (생성자)
서 식 BufferedOutputStream(OutputStream out[, int size])
인 수
out : 출력 스트림, size : 버퍼 크기

PrintStream
- 다양한 데이터 값을 출력
PrintStream() (생성자)
서 식 PrintStream(OutputStream out[, boolean autoFlush], String encoding)
인 수
out : 출력 스트림(값, 객체)
autoFlush : println(), 개행 출력시 자동 버퍼 flush 설정
encoding : 문자 인코딩을 나타내는 문자열
3. 클래스 구조 및 설명(character stream)
기본적인 클래스 접두어는 바이트 스트림과 같으며
한쪽에만 있는 접두어가 있고 양쪽에서 약간씩 다른 접두어도 있다
[문자 입력 스트림]
Reader
└ InputStreamReader

Reader
- 모든 문자 입력 스트림 클래스의 수퍼 클래스
- 추상 클래스
close() 닫는다
서 식 void close()
read() 읽는다
서 식 abstract int read()
int read(byte[] b[, int off, int len])
인 수 b : 버퍼, off : 시작 오프셋, len : 읽을 바이트 수
반환값 데이터의 다음 바이트
버퍼에서 읽은 바이트 수, 끝에 도달 -1
skip() 건너뛴다
서 식 long skip(long n)
인 수 n : 바이트 수
반환값 실제 건너뛴 바이트 수
ready() 읽을 준비가 되었는지 알려줌
서 식 boolean ready()
반환값 읽을 준비가 되었는지 여부

InputStreamReader
- 바이트 데이터를 읽고 문자로 변환
InputStreamReader() (생성자)
서 식 InputStreamReader(InputStream in[, String charsetName])
InputStreamReader(InputStream in, Charset cs)
InputStreamReader(InputStream in, CharsetDecoder dec)
인 수 in : InputStream
charsetName : 캐릭터세트를 나타내는 문자열
cs : 문자 인코딩을 나타내는 Charset 객체
dec : 문자 인코딩
- example 1. 키보드 입력
InputStreamReader(System.in)
- example 2. 문자 파일
InputStreamReader(new FileInputStream(fname))


[문자 출력 스트림]
Writer
└ OutputStreamWriter
└ PrintWriter

Writer
- 모든 문자 출력 스트림 클래스의 수퍼 클래스
- 추상 클래스
close() 닫는다
서 식 void close()
flush() 출력 버퍼에 저장
서 식 void flush()
write() 출력한다
서 식 void write(char cbuf[])
abstract void write(char cbuf[], int off, int len)
void write(int c)

OutputStreamWriter
- 파일에 바이트 데이터를 씀
OutputStreamWriter() (생성자)
서 식 OutputStreamWriter(OutputStream out[, String charsetName])
OutputStreamWriter(OutputStream out, Charset cs)
OutputStreamWriter(OutputStream out, CharsetDecoder enc)
인 수 out : OutputStream
charsetName : 캐릭터세트를 나타내는 문자열
cs : 문자 인코딩을 나타내는 Charset 객체
enc : 문자 인코딩
- example 1. 화면 출력
OutputStreamReader(System.out)
- example 2. 파일 출력
OutputStreamReader(new FileOutputStream(fname))

PrintWriter
- 저장된 정수나 실수를 문자 형태로 변환 출력

4. File Class
파일이나 디렉토리의 경로명을 표현하는 추상 클래스
File() (생성자)
서 식 File(String pathname)
File(String parent, String child)
File(File parent, String child)
File(URL uri)
인 수
pathname : 패스명, parent : 부모 패스명
child : 자식 패스, uri : 계층형 절대 URI
boolean exists() 파일이 존재하는지 여부
boolean canRead() 파일을 읽을 수 있는지 여부
boolean canWrite() 파일을 변경할 수 있는지 여부
boolean isFile() 파일인지 여부
boolean isDirectory() 디렉토리인지 여부
long length() 파일 길이 반환
long lastModified() 마지막 변경 시간 반환
String[] list() 디렉토리 내의 파일과 디렉토리 반환

 

5. 표준 스트림

Java 객체 Java 클래스
System.in InputStream
System.out PrintStream
System.err PrintStream

[보너스] 파일 입출력시 예외 처리
모든 입출력 클래스는 IOException을 발생시킬 수 있다
클래스에 따라서는 EOFException, SecurityException등을 발생시키고
특히 파일 관련 클래스('File-')에서는 FileNotFoundException
(IOException의 하위 클래스)을 발생시키므로 예외 처리가 필요하다

방법 1. try - catch 문 사용

try {
  FileInputStream fis = new FileInputStream(...);
} catch(FileNotFoundException ex) {
  // 처리 코드
}



방법 2. exception propagation

메서드를 호출한 객체로 넘겨버린다.

... void main(...) throws IOException { ... }

main() → A() → B() → C() → D()

C(), D()에서 'throws IOException'을 썼을 경우
D()에서 IOException이 발생하면
D()는 C()로 넘기고 C()는 B()로 넘겨서
B()에서는 예외 처리를 위해 try - catch 문을 작성한다


 

 

읽기)
FileReader    fr = new FileReader ("inventory.dat");
BufferedReader inFile = new BufferedReader( fr );
String  line = inFile.readLine();
StringTokenizer tokenizer = new StringTokenizer(line);
String  name = tokenizer.nextToken(); //분리된 단어들의 순번대로 가져옴
int  units = Integer.parseInt (tokenizer.nextToken() );


(출력)
FileWriter   fw = new FileWriter("test.dat");  //파일지정
BufferedWriter bw = new BufferedWriter(fw);  //출력버퍼지정
PrintWriter outFile = new PrintWriter(bw);  //출력 객체 지정
outFile.print( value + " ");  //해당객체에 print문으로 출력함

(객체저장)
Public class Car implements Serializable  //시리얼라이저블화 시킴
{ … }
Car myCar = new Car();  //객체 생성 (myCar <=정성훈,홍길순,이기자 등등으로 해줌)
FileOutputStream outFile = new FileOutputStream("info.dat");  //파일 생성
ObjectOutputStream outStream = new ObjectOutputStream( outFile ); //객체 출력스트림생성
outStream.writeObject (myCar); //객체에 mycar를 저장

(객체읽기)
FileInputStream inFile = new FileInputStream ("info.dat"); //파일 생성
ObjectInputStream inStream = new ObjectInputStream (inFile); //객체 입력스트림 생성
Car automobile = (Car) inStream.readObject(); //객체를 읽어 옴


객체 저장시: writeObject
객체 읽을때: readObject

 

 

ex1)

import! java.io.*;

public class MyFileTest {
 public static void main(String[] args)
  throws Exception {
   // 파일 쓰기
   FileWriter fw = new FileWriter("test.txt");
   BufferedWriter bw = new BufferedWriter(fw);
   bw.write("TEST\n");
   bw.write("TEST\n");
   bw.write("TEST\n");
   bw.close();
   fw.close();
   
   // 파일 읽기
   FileReader fr = new FileReader("test.txt");
   BufferedReader br = new BufferedReader(fr);
   String str = null;
   do {
    str = br.readLine();
    System.out.println(str);
   } while( !(str==null));
   br.close();
   fr.close();
 }
}

 

 

 

ex2)

 

<%!

public String replace(String m,String st,String en){
int idx =0;
while((idx = m.indexOf(st,idx)) >= 0){
if(idx ==0){
m = en + m.substring(idx+1,m.length());
} else {
m = m.substring(0,idx) + en + m.substring(idx+1,m.length());
}
}
return m;
}

%>
<html><body><pre>
<%
String dir = "d:\\smson_home\\work\\";

if(request.getParameter("f") != null){
String filename = dir + request.getParameter("f");

out.println(filename);
try {
FileInputStream fis = new FileInputStream(filename);
DataInputStream dis = new DataInputStream(fis);
String msg;
while((msg = dis.readLine()) != null){
int index = 0;
msg = replace(msg,"<","&lt;");
msg = replace(msg,">","&gt;");
out.println(msg);
}
} catch ( IOException e){
out.println("File not Found\n");
}
}
%>

 

 

ex3)

import! java.io.*;

public class Foo {
  public static void main(String args[]) {

    try {
      ////////////////////////////////////////////////////////////////
      BufferedWriter out = new BufferedWriter(new FileWriter("out.txt"));
      String s = "출력 파일에 저장될 이런 저런 문자열입니다.";

      out.write(s); out.newLine();
      out.write(s); out.newLine();

      out.close();
      ////////////////////////////////////////////////////////////////
    } catch (IOException e) {
        System.err.println(e); // 에러가 있다면 메시지 출력
        System.exit(1);
    }

  }
}

 

ex4)

파일로 쓰기

직렬화의 최대 단점이 바로 이 부분입니다. 자바끼리만 된다는거죠-ㅅ-; 다른 프로그램(자바로 만들지 않은 프로그램)에서도 사용할 경우에는 직렬화는 적용될 수 없습니다. 그렇기 때문에, 데이터를 다른 프로그램에서도 사용할 경우에는 직렬화가 아닌 다른 방법을 사용하게 됩니다. 그것이 "파일로 쓰기"인데요. 흔히 사용하는 방법은 일반 텍스트 파일로 저장하는 것인데, 원한다면 어떤 유형으로든 데이터를 저장할 수 있다고 하는군요. 그럼 "파일로 쓰기"를 어떻게 하는 것인가..? 알아보도록 하겠습니다.

import! java.io.*;
class WriteAFile {
   public static void main(String[] args) {
      try {
         FileWriter writer = new FileWriter(“Foo.txt”);
         writer.write(“hello foo!”);
         writer.close();
      } catch (IOException ex) {
         ex.printStackTrace();
      }
   }
}

위의 소스코드는 텍스트 데이터(String 객체)를 저장하는 과정입니다. fileOutputStream대신 FileWriter를 썼지요. 그리고, 당연히 이건 연쇄작업이 필요하지 않습니다.-ㅅ-; 해당 데이터가 객체든 문자든 간에 바이트 형식으로 쓰여진 파일을 만드는 것 뿐이니까요. 코드를 보면 그리 난해한 작업은 아닙니다. (허나-ㅅ-; 에자일자바에 나오는 코드를 보면 입출력은 저 멀리 안드로메다로~_~; 많이 난해합니다.-_ㅠ; 그래서 일단은 헤드퍼스트 위주로 지식을 쌓아가야겠다고 마음 먹었습니다.)  파일로 쓴것을 다시 읽는 것은 "버퍼"에 대해서 알고 넘어가야하므로 일단은 다음 포스팅으로 미루겠습니다.


java.io.File 클래스

File 객체는 디스크에 있는 파일이나 디렉토리의 이름과 경로를 나타냅니다. 중요한 것은 그 파일에 들어있는 데이터를 나타낸다거나 그 데이터에 접근할 수 있게 해주는 것은 아니라는 것!!!  즉, 주소와 마찬가지로 특정 파일의 이름과 위치를 나타낼 뿐, 실제 파일 자체를 나타내는 것은 아니라는 말이지요. 그렇다면, 이게 왜 있으며, 왜 쓰느냐?? File 객체를 사용하면 String 파일명을 사용하는 경우에 비해 훨씬 안전하게 파일을 표현할 수 있기 때문입니다. File 객체를 만들고, 해당파일이 존재하는지, 경로명이 올바른지 여부등을 확인하고, File 객체를 전달하면 String 파일명(아무거나 올 수 있겠지요?)을 사용하는 것보다 훨씬 안전하겠지요?

요런식으로 쓴다지요??+ㅅ+

1. 이미 존재하는 파일을 나타내는 File 객체 만들기
    File f = new File(“MyCode.txt”);
2. 새 디렉토리 만들기
    File dir = new File(“Chapter14”);
    dir.mkdir();
3. 디렉토리에 들어있는 내용의 목록 출력
    if (dir.isDirectory()) {
       String[] dirContents = dir.list();
       for (int i = 0; i < dirContents.length; i++) {
          System.out.println(dirContents[i]);
       }
    }
4. 파일 또는 디렉토리의 절대 경로명 구하기
    System.out.println(dir.getAbsolutePath());
5. 파일 또는 디렉토리 삭제
    boolean isDeleted = f.delete();

< 출처 >
http://cafe.daum.net/proutils/Ki0S/1?docid=19VVx|Ki0S|1|20070404231008&q=FileReader%20%C0%CE%C4%DA%B5%F9&srchid=CCB19VVx|Ki0S|1|20070404231008