I/O流
Posted 冬有雪
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了I/O流相关的知识,希望对你有一定的参考价值。
一、字节流和字符流
流是一种有方向的字节/字符数据序列。
实现输入/输出操作的类库在java.io 包中。包中有一组支持打开流、向流写数据、从流读取数据和关闭流等操作的
类,要使用这些类,程序必须导入java.io 包。
二、File 对象
建立输入输出流对象之前可以先建立一个File(文件)对象。File 对象是File 类的实例。File 对象对应一个目录或文件,对象的属性包括文件路径、名字、文件长度、可否读写等。File 对象只用来命名文件、查询文件属性和处理目
录,不提供读写文件操作。
常用的构造方法:
(1) File(String s),由s 确定File 对象的文件名。
(2) File(String directory ,String s),由directory 确定File 对象的文件目录,由s 确定文件名。
以下是创建File 对象的示意代码:
File f1 = new file(“/mydir/myfile.txt”);
File f2 = new File(“/mydir”,”myfile.text”);
//使用File 创建文件
import java.io.*;
public class CreateNewFile
//创建一个方法完成创建文件的目的,文件的第一个参数是文件路径和文件名,第二个参数是文件内容
//如:myfile.doc HelloJava!
public void createNewFile(String fileDirectoryAndName,String fileContent)
try
String fileName = fileDirectoryAndName;
//创建File对象,参数为String类型,表示目录名
File myFile = new File(fileName);
//判断文件是否存在,如果不存在则调用createNewFile()方法创建新目录,否则跳至异常处理代码
if(!myFile.exists())
myFile.createNewFile();
else //如果不存在则扔出异常
throw new Exception("The new file already exists!");
//下面把数据写入创建的文件,首先新建文件名为参数创建FileWriter对象
FileWriter resultFile = new FileWriter(myFile);
//把该对象包装进PrinterWriter对象
PrintWriter myNewFile = new PrintWriter(resultFile);
//再通过PrinterWriter对象的println()方法把字符串数据写入新建文件
myNewFile.println(fileContent);
resultFile.close(); //关闭文件写入流
catch(Exception ex)
System.out.println("无法创建新文件!");
ex.printStackTrace();
public static void main(String[] args)
//创建类的对象并调用该对象的createNewFile()方法,创建新文件并写入数据
CreateNewFile createFile = new CreateNewFile();
createFile.createNewFile(args[0],args[1]);
三、流对象
Java 程序的输入和输出流称为流对象,文件读写的主要操作包括:建立流对象、读数据、写数据和关闭流。输入输出流由文件名或File 对象创建。
根据输入输出数据的类型是字节还是字符,java.io 提供两种基本抽象类:一种用于读写字节,另一种用于读写字符。
字节流用于读写二进制数据,比如图像和声音文件等。字节流数据是8位的,由InputStream 类和OutputStream
类为字节流提供API 和部分实现。字节流读和写操作由FileInputStream 类和FileOutputStream 类提供支持。它们分别是InputStream 和OutputStream 类的子类。
字符流数据是16 位的Unicode 字符,字符流能处理Unicode 字符集中的任何字符,由Reader 类和Writer 类为字符流提供API 和部分实现。读和写操作由FileReader 类和FileWriter 类提供支持。它们分别是Reader 和Writer 的子类。
1. 建立流对象
通过流的构造方法建立流对象,创建输入输出流对象的常用构造方法用2种,下面以创建FileInputStream 类的流对象为例说明创建流对象的方法,创建FileOutputStream 类、FileReader 类和FileWriter 类的流对象与此完全类似。
- (1) FileInputStream(String name),直接指定的文件名创建输入流。
- (2) FileInputStream(File filename),用文件对象创建输入流。
由于使用输入流的构造方法创建输入流时,可能会出现FileNotFoundException 异常。所以创建输入流的代码必须出现在try…catch 语句结构中,让程序能检测并处理这个异常。所以,创建输入流代码呈以下形式:
try
FileInputStream ins = new FileinputStream(“myfile.data”);//创建输入流对象。
}catch(FileNotFoundException e)
System.out.println(“文件找不到:”+e);
上述代码把输入流对象与文件关联起来,使用catch 块捕获并处理文件找不到异常。
2. 输入流的常用方法
FileInputStream 类包含下面用于读字节和字节数组的方法:
(1) int read()从输入流读取下一个字节,返回一个整数,整数范围在0~255 之间。
(2) int read(byte b[]),从输入流读取长度为b.length 的字节数据,写入到字节数组b,并返回实际所读取的字
节数。
(3) int read(byte b[],int off, int len),从数据流中读取长度为len 的字节数据,写入到字节数组b 中从下标off 开始的数组元素中,并返回实际读取的字节数。
使用以上三个方法时,如果在读数据之前,已到达输入的末端位置,没有读入一个字节数据,用返回-1 表示流在读之前已结束。
FileReader 类包含下面用于读字符和字符数组的方法:
(1) int read(),从输入流读取下一个字符。如果读前已到流的末尾,则返回-1。
(2) int read(char b[]),从输入流读取长度为b.length 的字符数据,写入到字符数组b,并返回实际所读取的
字符数。
(3) int read(char b[],int off,int len),从数据流中读取长度为len 的字符数据,写入到字符数组b 中从下标off 开始的数组元素中,并返回实际读取的字符数。
对于输入流,另外还有一个常用的方法:
long skip(long n),从输入流的当前读位置起向前移动n 个字节/字符,并返回实际跳过的字节/字符数。
3. 输出流的常用方法
FileOutputStream 类包含下面用于输出字节和字节数组的方法:
(1) int write(int c),输出一个字节。
(2) int write(byte b[]),输出存于字节数组b 中的字节数据。
(3) int write(byte b[],int off,int len),输出字节数组b 中从下标off 开始的多至len 个字节。
FileWriter 类也包含用于输出字符和字符数组的方法:
(1) int write(int c),输出一个字符。
(2) int write(char b[]),输出存于字符数组b 中的字符数据。
(3) int write(char b[],int off,int len),输出字符数组b 中人下标off 开始的多至len 个字符。
对于输出流,另外还有一个常用方法:
void flush(),刷空输出流,并且输出所有存储在缓冲区的内容。
流使用结束后,关闭流并且释放与该流相关的资源用方法close()。为了程序安全,也为了提高计算机的资源利用率。流使用结束后,程序应及时关闭它。
示例:
//使用字符流将一个文件的内容复制到另一个文件
import java.io.*;
public class ReaderWriter
public static void main(String[] args)
File iFile = new File("f1.txt");
File oFile = new File("f2.txt");
int cache;
try
FileReader in = new FileReader(iFile);
FileWriter out = new FileWriter(oFile);
while((cache = in.read()) != -1)
out.write(cache);
in.close();
out.close();
System.out.println("Finish!");
catch(FileNotFoundException fnfe)
System.out.println("File not Found!");
catch(IOException ioe)
System.out.println("Error!");
四、缓冲式输入输出
当程序处理的文件按行组织,并且行不是定长时,用前面所述的流类实现很不方便。程序如果要按行输入输出,需
采用缓冲式输入输出方式。
1.缓冲式输入
采用缓冲式输入时,对于程序的输入请求,系统一次性输入足够多的内容放在内存缓冲区中。供程序以后的输
入请求使用,待缓冲区内容用完,再一次性输入足够多的数据。
程序要采用缓冲式输入,只要先创建FileReader 对象,再利用FileReader 对象创建BufferedReader 对象,习
惯称为FileReader 对象接到BufferedReader 对象上。如以下代码所示:
BufferedReader in;
file = new FileReader(“abc.txt”);//创建fileReader 对象
in = new BufferedReader(file);//接到BufferedReader 类对象上
in.readLine();
示例:
//BufferedReader示例
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
class BufferedDemo extends JFrame implements ActionListener
JTextArea text;
JButton button;
FileReader file;
BufferedReader in;
BufferedDemo()
super("BufferedReader Test");
Container con = this.getContentPane();
con.setSize(200,500);
con.setLayout(new BorderLayout());
text = new JTextArea(20,50);
text.setBackground(Color.cyan);
button = new JButton("Read File");
button.addActionListener(this);
JScrollPane jsp = new JScrollPane(text);
con.add(jsp,BorderLayout.CENTER);
con.add(button,"South");
this.setVisible(true);
this.pack();
try
File f = new File("F:\\\\android\\\\code\\\\BufferedTest.java");
file = new FileReader(f);
in = new BufferedReader(file);
catch(FileNotFoundException fnfe)
text.setText("file not found");
button.removeActionListener(this);
public void actionPerformed(ActionEvent e)
String s;
if(e.getSource() == button)
try
while((s = in.readLine()) != null)
text.append(s + '\\n');
catch(IOException ioe)
text.setText("Read Error");
public class BufferedTest
public static void main(String[] args)
new BufferedDemo();
2.缓冲式输出
采用缓冲式输出时,对于程序的输出请求,系统先将内容暂存于缓冲区,待缓冲区满或输出结束,才将暂存于缓冲
区中的内容输出到流的目的地。
BufferedWriter 类是提供缓冲式输出的类。程序只要先创建FileWriter 对象,再选用FileWriter 对象创建BufferedWriter 对象,习惯称为FileWriter 对象接到BufferedWriter 对象上。对BufferedWriter 对象使用write()方法就能实现缓冲式输出。采用缓冲式输出时,write()方法只是将字符串写入到系统内设的缓冲区,等缓冲区满后,系统自动将缓冲区中内容写入到文件。如果想立即写入到文件,则需要调用flush()方法。
示例:
//BufferedWriter 示例
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
class BufWriDemo extends JFrame implements ActionListener
JTextArea text;
JButton button;
FileWriter file;
BufferedWriter out;
BufWriDemo()
super("BufferedWriter Test");
Container con = this.getContentPane();
con.setLayout(new BorderLayout());
text = new JTextArea(20,30);
text.setBackground(Color.gray);
text.setText("亦余心之所善兮,虽九死其犹未悔!");
button = new JButton("Writer File");
button.addActionListener(this);
JScrollPane jsp = new JScrollPane(text);
con.setSize(40,40);
con.add(jsp,BorderLayout.CENTER);
con.add(button,"South");
con.setVisible(true);
this.pack();
try
file = new FileWriter("filewriter.txt");
out = new BufferedWriter(file);
catch(IOException ioe)
public void actionPerformed(ActionEvent e)
String s;
if(e.getSource() == button)
try
out.write(text.getText(),0,(text.getText()).length());
out.flush();
text.setText(null);
//System.exit(0);
catch(IOException exp)
text.setText("File Write Error\\n");
System.exit(-1);
public class BufferedWriterTest
public static void main(String[] args)
BufWriDemo bwd = new BufWriDemo();
bwd.pack();
bwd.setVisible(true);
五、随机访问
流在某些应用中,不希望顺序读写流。例如,跳过部分不需要的数据,去读更后面的数据;或者对早先读过的数据
要重新读入等。这样的应用需采用随机访问方式,本节介绍文件随机访问的方法。
文件随机访问可利用RandomAccessFile 类实现,RandomAccessFile 类创建的流既可以随机输出,也可以随机输入。
1.RandomAccessFile 类构造方法
RandomAccessFile 类常用的构造方法是RandomAccessFile(String name, String mode)和RandomAcessFile(File file,String mode)。参数mode 取值:“r”(只读)或 “rw”(可读写)。构造方法可能产生“文件不存在”异常,创建对象的代码应能捕获FileNotFoundException 异常。对流进行读写操作时,还应该能捕获IOException 异常。
2.RandomAcessFile 类读写文件的方法
RandomAccessFile 类常用的读写文件方法有:
(1) int read(),读取一个字节,当前读位置往前移动8个二进制位。
(2) int read(byte b[]),把文件中的数据读到一个字节数组,当前读位置顺次往前移动。
(3) int read(byte b[],int offset, int length),从文件中读取length 个字节,把读入的字节存到数组b[],存储从偏移量为offset 的位置开始;当前读位置也往前移动。
(4) String readLine(),读取文件中的一行字节,遇到换行,结束一次读入过程。
(5) String readUTF(),从一个UTF 格式的文件中读取一个字符串。
(6) boolean readBoolean(),读取一个布尔值。
(7) byte readByte(),读取一个字节。
(8) short readShort(),读取一个short 型整数。
(9) long readLong(),读取一个long 型整数。
(10) char readChar(),读取一个字符。
(11) int readInt(),读取一个整数。
(12) void writeBoolean(boolean v),写一个布尔值。
(13) void writeByte(int v),写一个字节。
(14) void writeShort(int v),写一个short 型整数。
(15) void writeChar(int v),写一个字符。
(16) void writeInt(int v),写一个型整数。
(17) void writeLong(long v),写一个long 型整数。
(18) void writeFloat(float v),写一个浮点数。
(19) void writeDouble(double v),写一个双精度浮点数。
(20) void writeBytes(String v),写一个字符串作为字符序列,写这个字符串。
(21) void writeChars(String v),写一个字符串作为字符序列,写这个字符串。
(22) void seek(long offset),移动当前读写位置距文件开始offset 位置。
//RandomAccessFile Demo
import java.io.*;
public class RandomAccessFileDemo
public static void main(String[] args)
RandomAccessFile io = null;
double[] data = 234.2134,231,523,2342.34,234.645,32,6345.32;
try
io = new RandomAccessFile("doubleData.txt","rw");
for(int i = 0; i < data.length; i++)
io.writeDouble(data[i]);
for(int i = data.length - 1; i >= 0; i--) //按
相反顺序读出这些写入的整数
io.seek(i * 8);//long 型数据占8个字节,第i 个整数自i*8 字节开始
System.out.print(" " + io.readDouble() + ((i == 0) ? "\\n" : ","));
io.close();
catch(FileNotFoundException e1)
System.out.println("File not found" + e1);
catch(IOException e2)
System.out.println("File read/write error" + e2);
示例2:
import java.io.*;
public class RandomAccessDemo
public static void main(String[] args)
try
RandomAccessFile f = new RandomAccessFile("RandomAccessDemo.java","r");
double cursorPosition = 0;
// double fileLength = f.length();
while(cursorPosition < f.length())
String s = f.readLine();
System.out.println(s);
cursorPosition = f.getFilePointer();//程序利用getFilePointer()得到文件的当前位置,与fileLength()文件的长度比较用于控制循环。
f.close();
catch(FileNotFoundException e1)
System.out.println("File not found");
catch(IOException e2)
System.out.println("File read error");
3.文件对话框
大多数应用程序要使用文件,或读取文件的内容,或将数据保存于文件中,其中文件通过文件对话框指定。本节介绍程序使用文件对话框打开和保存文件的方法。可以用javax.swing 包中的类JFileChooser 实现打开和保存文件对
话框。
1. JFileChooser 类的构造方法
(1) JFileChooser(),建立一个JFileChooser 对象,默认的文件对话框路径是用户的Home 目录。
(2) JFileChooser(String currentDirectoryPath),建立一个JFileChooser 对象,并设置文件对话框的打开路径。
2. JFileChooser 类的其他常用方法
(1) showOpenDialog(),打开“打开文件对话框”。
(2) showSaveDialog(),打开“保存文件对话框”。
文件对话框打开后,在用户按下按钮或关闭对话框时,上述两个方法会返回一个整数值,这个整数值是以下三个之一:
JFileChooser.CANCEL_OPTION,用户按下“撤销”按钮。
JFileChooser.APPROVE_OPTION,用户按下“打开/保存”按钮。
JFileChooser.ERROR_OPTION,有错,或是对话框非正常关闭。
当程序发现用户选择了文件并按下了“打开/保存”按钮后,程序就可以利用getSelectedFile()方法取得文件对象,并利用这个文件对象用方法getName()取得文件的名称,用方法getPath()取得文件的路径。
3. 设置筛选条件
在打开文件对话框中,还可以设置筛选条件,即指定文件的类型。使用FileFilter 类,该类预设两个方法,分别是accept(File f),与getDescription()。当目录中的文件与筛选条件相符时,方法accept()返回true,并将此文件名显示在对话框中。而getDescription()方法则是对筛选条件的描述,由程序指定,例如,“*.java”等。
由于FileFilter 类是一个抽象类,程序要设置打开文件对话框的文件筛选条件,就应该继承这个类,编写一个实现类,实现上述两个方法。然后,就可以使用JFileChooser 类addChoosableFileFilter()方法,或者是setFileFilter()方法设置筛选条件。
示例如下:
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.filechooser.*;
import javax.swing.filechooser.FileFilter;
public class JFileChooserTest
public static void main(String[] args)
FrameFiledialog f = new FrameFiledialog();
class FrameFiledialog extends JFrame implements ActionListener
JFileChooser filedialog = null;
JLabel label = new JLabel(" ",JLabel.CENTER);
JButton b1,b2;
JTextArea text;
FrameFiledialog()
super("Window with dialog");
Container con = this.getContentPane();
con.setLayout(new BorderLayout());
con.setSize(40,50);
JPanel p = new JPanel();
b1 = new JButton("Open file");
b2 = new JButton("Save file");
b1.addActionListener(this);
b2.addActionListener(this);
p.add(b1);
p.add(b2);
text = new JTextArea(20,30);
JScrollPane jsp = new JScrollPane(text);
filedialog = new JFileChooser("F:\\\\android\\\\workspace");
// filedialog.setControlButtonAreShown(true);
filedialog.addChoosableFileFilter(new MyFileFilter("txt"));
filedialog.addChoosableFileFilter(new MyFileFilter("java"));
text.setBackground(Color.cyan);
con.add(jsp,BorderLayout.CENTER);
con.add(label,BorderLayout.NORTH);
con.add(p,BorderLayout.SOUTH);
this.setVisible(true);
this.pack();
public void actionPerformed(ActionEvent e)
File file = null;
int result;
if(e.getSource() == b1)
filedialog.setDialogTitle("Open file");
result = filedialog.showOpenDialog(this);
text.setText("");
if(result == JFileChooser.APPROVE_OPTION)
file = filedialog.getSelectedFile();
label.setText("your opened file name is: " + file.getName());
else if(result == JFileChooser.CANCEL_OPTION)
label.setText("you don't selected any file");
FileInputStream fileStream = null;
if(file != null)
try
fileStream = new FileInputStream(file);
catch(FileNotFoundException nfe)
label.setText("file not found");
return;
int readByte;
try
while((readByte = fileStream.read()) != -1)
text.append(String.valueOf((char)readByte));
fileStream.close();
catch(IOException ie)
label.setText("read file error");
else if(e.getSource() == b2)
filedialog.setDialogTitle("save file");
result = filedialog.showSaveDialog(this);
file = null;
String fileName;
if(result == JFileChooser.APPROVE_OPTION)
file = filedialog.getSelectedFile();
label.setText("the file name you seleted if: " + file.getName());
else if(result == JFileChooser.APPROVE_OPTION)
label.setText("你没有选择任何文件");
FileOutputStream fileStream = null;
if(file !=null)
tryfileStream = new FileOutputStream(file);
catch(FileNotFoundException nfe)
label.setText("文件没有发现");return;
String content = text.getText();
try
fileStream.write(content.getBytes());
fileStream.close();
catch(IOException ie)label.setText("写文件出错");
class MyFileFilter extends FileFilter
String ext;
MyFileFilter(String t)ext =t;
public boolean accept(File file)
if(file.isDirectory()) return true;
String fn = file.getName();
int index = fn.lastIndexOf('.');
if(index >0&& index <fn.length()-1)
String extension = fn.substring(index+1).toLowerCase();
if(extension.equals(ext))return true;
return false;
public String getDescription()
if(ext.equals("java"))return "JAVA Source File(*.java)";
if(ext.equals("txt"))return "Txt File(*.txt)";
return "";
以上是关于I/O流的主要内容,如果未能解决你的问题,请参考以下文章