第一讲 IO概述
一、概述
1、IO:Input Stream的缩写。
2、特点:
1)IO可以用来处理设备间的数据传输;
2)Java对数据的操作是通过流的方式;
3)Java用于操作流的对象都在io包中;
4)流按操作数据分为两种:字节流、字符流;
5)流按流向分为:输入流、输出流;
6)IO流只能操作数据,不能操作文件(如:通过IO流可以向一个文件写入数据,却无法删除这个文件)。
3、IO流常用基类
1)字节流的抽象基类:InputStream、OutputStream;
2)字符流的抽象基类:Reader、Writer;
3)由这四个基础类派生的子类,名称都是以其父类名作为子类名的后缀,以其操作对象(或功能)作为前缀(例如:InputStream的子类FileInputStream,Reader的子类FileReader)。
第二讲 字符流
一、概述
1、字符流有两个基类:Reader、Writer;
2、字符流中的对象融合了编码表,默认使用当前系统的编码;
3、字符流只用于处理文字数据,字节流可以处理多媒体数据(如图片、视频文件等);
4、既然IO流是用于操作数据的,那么数据的最常见体现形式就是文件。通过查阅API,找到一个专门用于操作文件的Writer子类对象:FileWriter。后缀是父类名,前缀是流对象的功能。该流对象一被初始化就必须有被操作的文件存在。
二、字符流的基本操作
1、写入字符流步骤
1)创建一个FileWriter对象,该对象一被初始化,就必须要明确指定被操作的文件。如果该目录下已有同名文件,则同名文件将被覆盖。其实这一步就是在明确数据要存放的目的地。
2)调用write(String s)方法,将字符串写入到流中(写入内存)。
3)调用flush()方法,刷新该流的缓冲,将内存(流)中的数据刷新到目的地(文件)中。flush刷新后,流可以继续使用。
4)调用close()方法,关闭流资源。执行close()方法在关闭前会刷新一次内部的缓冲数据,并将数据刷新到目的地中。close会关闭流,因此调用close方法后将不能再写入数据。
备注
1)java自身不能写入数据,而是调用系统内部方式完成数据的写入,使用系统资源后,一定要关闭资源,否则很可能会造成资源泄漏。
2)文件的数据的续写是通过构造函数FileWriter(String s, boolean append),在创建对象时,传递一个true参数,代表不覆盖已有的文件,而是在已有文件的末尾处进行数据续写,如果文件不存在就会在内部调用File的API创建文件(Windows系统中的文件内换行用\r\n两个转义字符表示,在Linux系统中只用\n表示换行)。
3)由于在创建对象时,需要制定创建文件的位置,如果指定的位置不存在,就就会发生IOException,所以在整个步骤中,需要对IO异常进行try-catch处理。
使用示例:
package com.dawndaybreak.ioexample;
import java.io.FileWriter;
import java.io.IOException;
/**
*
* 通过FileWriter实现对文件的写入、续写操作
*
* @author dawn
*
*/
public class WriterDemo {
public static void main(String[] args) {
String filePath = "E:/demo.txt";
String[] arrays = { "Hello World!", "dd" };
FileWriterUtil.writerData(filePath, arrays);
FileWriterUtil.writerData(filePath, arrays, true);
}
}
class FileWriterUtil {
/**
* 添加多行字符到指定文件
*
* @param filePath
* 文件目录
* @param arrays
* 写入数据,每个不等于null的对象为一行数据
*/
public static void writerData(String filePath, Object[] arrays) {
FileWriter writer = null;
try {
writer = new FileWriter(filePath);
for (Object line : arrays) {
if (line != null) {
writer.write(String.valueOf(line));
writer.write(getLineSeparator());
writer.flush();
}
}
} catch (IOException e) {
throw new RuntimeException("文件写入失败,可能缺失权限或没有指定的盘符", e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 添加多行字符到指定文件
*
* @param filePath
* 文件目录
* @param arrays
* 写入数据,每个不等于null的对象为作为一行数据
* @param append
* 追加,append为true则表示不覆盖原文件,只追加内容;否则覆盖原文件
*/
public static void writerData(String filePath, Object[] arrays,
boolean append) {
FileWriter writer = null;
try {
writer = new FileWriter(filePath, append);
for (Object line : arrays) {
if (line != null) {
writer.write(String.valueOf(line));
writer.write(getLineSeparator());
}
}
} catch (IOException e) {
throw new RuntimeException("文件写入失败,可能缺失权限或没有指定的盘符", e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static String getLineSeparator() {
String osName = System.getProperty("os.name");
if (osName != null && osName.contains("Windows")) {
return "\r\n";
}
return "\n";
}
}
1)创建一个文件读取流对象(FileReader Object),和指定名称的文件相关联。如果指定的文件不存在,将会抛出FileNotFoundException异常。
2)调用read()方法。read():一次读一个字符;read(char[] cbuffer):通过字符数组读取,每次读取都返回填充到数组的字符量
3)为避免资源泄漏,读取后必须调用close()关闭流。
使用示例:
package com.dawndaybreak.ioexample;
import java.io.FileReader;
import java.io.IOException;
/**
*
* 通过FileReader实现对指定文件的读取操作
*
* @author dawn
*
*/
public class ReaderDemo {
public static void main(String[] args) {
String filePath = "E:/demo.txt";
String content = FileReaderUtils.readData(filePath);
System.out.println(content);
System.out.println(FileReaderUtils.readDataByBuffer(filePath));
}
}
class FileReaderUtils {
/**
* 逐字符读取
*
* @param filePath
* 文件目录
* @return 文件内容
*/
public static String readData(String filePath) {
FileReader reader = null;
StringBuffer buffer = new StringBuffer();
try {
reader = new FileReader(filePath);
int ch = -1;
while ((ch = reader.read()) != -1) {
buffer.append((char) ch);
}
} catch (IOException e) {
throw new RuntimeException("读取失败,可能引起的元:指定文件不存在或其他因素", e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return buffer.toString();
}
/**
* 通过数组读取数据
*
* @param filePath
* 文件目录
* @return 文件内容
*/
public static String readDataByBuffer(String filePath) {
FileReader reader = null;
StringBuffer buffer = new StringBuffer();
try {
reader = new FileReader(filePath);
int len = -1;
char[] cbuffer = new char[1024];
while ((len = reader.read(cbuffer)) != -1) {
buffer.append(new String(cbuffer, 0, len));
}
} catch (IOException e) {
throw new RuntimeException("读取失败,可能引起的元:指定文件不存在或其他因素", e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return buffer.toString();
}
}
文件的拷贝:
文件的拷贝其实就是将一个目的地的数据读取写入到另一个目的地
package com.dawndaybreak.ioexample;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
/**
* 复制文件,可复制图片、文本、压缩包等
*
* @author dawn
*
*/
public class CopyFile {
public static void main(String[] args) {
// copy file
String sourcePath = "E:/demo.txt";
String outputPath = "E:/demo-new.txt";
FileUtil.getInstance().copyFile(sourcePath, outputPath);
}
}
class FileUtil {
private Reader reader;
private Writer writer;
public static FileUtil getInstance() {
return new FileUtil();
}
private FileUtil() {
}
/**
* 复制文件到另一个目录
*
* @param sourcePath
* 源文件目录,即被复制文件目录
* @param outputPath
* 输出文件目录,即复制出来的文件存放目录
*/
public void copyFile(String sourcePath, String outputPath) {
try {
initStream(sourcePath, outputPath);
copyFileToDir();
} catch (Exception e) {
throw new RuntimeException("文件复制失败", e);
} finally {
close();
}
}
private void close() {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void copyFileToDir() throws IOException {
int ch = -1;
while ((ch = reader.read()) != -1) {
writer.write(ch);
}
writer.flush();
}
private void initStream(String sourcePath, String outputPath)
throws IOException {
reader = new FileReader(sourcePath);
writer = new FileWriter(outputPath);
}
}
概述
1、缓冲区的出现是为了提高流的读写效率,所以在缓冲区创建之前,要先创建流对象,并将流对象作为参数传递给缓冲区的构造函数。
2、缓冲技术原理:在此对象中封装一个数字,每次将数据写入数字,在数组装满数据会调用flush方法后将数据一次性取出写入文件。
3、写入缓冲区BufferedWriter的步骤:
1)创建一个字符写入流对象(FileWriter Object)
如:FileWriter fw = new FileWriter("E:/demo.txt");
2)为了提高字符流写入效率,加入缓冲技术。只要将需要被提高效率的流作为参数传递给缓冲区的构造函数即可。
如:BufferedWriter bw = new BufferedWriter(fw);
3)调用write方法写入数据到目标文件
如:bw.write("Hello World!");
4)刷新缓冲区(只要用到缓冲区,就要记得刷新。关闭流同样会刷新,为了排除意外事故,保证数据存在,建议写入一次就刷新一次)
如:bw.flush();
5)关闭缓冲区(缓冲区操作的是流对象,关闭缓冲区其实就是关闭缓冲区中的流对象)
如:bw.close();
技巧:BufferedWriter提供了一个跨平台的换行符newLine()方法,可以在不同操作系统上调用,用作数据换行。
如:bw.newLine();
4、读取流缓冲区BufferedReader
该缓冲区提供了一个一次读一行的方法readLine,方便于堆文本数据的获取,当返回null时表示读到文件末尾。readLine方法返回的时候,只返回回车符之前的数据内容。并不返回回车符。
readLine方法原理:无论是读一行。或者读取多个字符。其实最终都是在在硬盘上一个一个读取。所以最终使用的还是read方法一次读一个的方法。
读取缓冲区BufferedReader的步骤
1)创建一个读取流对象和文件相关联
如:FileReader fr = new FileReader("E:\demo.txt");
2)为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲区对象的构造函数。
如:BufferedReader br = new BufferedReader(fr);
3)调用该缓冲区提供的readLine方法一行一行读取,如果到达文件末尾,则返回null
如:String sLine = br.readLine();
4)关闭流资源
如:br.close();
使用示例(复制一个文本文件):
package com.dawndaybreak.ioexample;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* 复制文本文件,通过缓冲技术
*
* @author dawn
*
*/
public class BufferedCopyFile {
public static void main(String[] args) {
// // copy file
// String sourcePath = "E:/demo.txt";
// String outputPath = "E:/demo-new.txt";
// FileUtil.getInstance().copyFile(sourcePath, outputPath);
// copy image file
String sourcePath = "E:/img1.jpg";
String outputPath = "E:/img2.jpg";
FileUtil.getInstance().copyFile(sourcePath, outputPath);
}
}
class BufferedFileUtil {
private BufferedReader reader;
private BufferedWriter writer;
public static BufferedFileUtil getInstance() {
return new BufferedFileUtil();
}
private BufferedFileUtil() {
}
/**
* 复制文件到另一个目录
*
* @param sourcePath
* 源文件目录,即被复制文件目录
* @param outputPath
* 输出文件目录,即复制出来的文件存放目录
*/
public void copyFile(String sourcePath, String outputPath) {
try {
initStream(sourcePath, outputPath);
copyFileToDir();
} catch (Exception e) {
throw new RuntimeException("文件复制失败", e);
} finally {
close();
}
}
private void close() {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void copyFileToDir() throws IOException {
String sLine = null;
while ((sLine = reader.readLine()) != null) {
writer.write(sLine);
}
writer.flush();
}
private void initStream(String sourcePath, String outputPath)
throws IOException {
reader = new BufferedReader(new FileReader(sourcePath));
writer = new BufferedWriter(new FileWriter(outputPath));
}
}
原理:可根据BufferedReader类中特有一行一行读取方法readLine()的原理,自定义一个类中包含相同功能的方法。
实现步骤:
1)初始化自定义类,加入流对象;
2)定义一个临时容器,原BufferedReader封装的是字符数组,此类中可定义一个StringBuilder的容器,最终可实现字符串的提取。
实现示例(以BufferedReader为例):
package com.dawndaybreak.ioexample;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
/**
* 测试自定义BufferedReader
*
* @author dawn
*
*/
public class MyBufferedReaderTest {
public static void main(String[] args) throws Exception {
MyBufferedReader br = new MyBufferedReader(new FileReader("E:/demo.txt"));
String sLine = null;
while ((sLine = br.readLine()) != null) {
System.out.println(sLine);
}
br.close();
}
}
/**
* 实现自定义BufferedReader
*
* @author dawn
*
*/
class MyBufferedReader extends Reader {
private Reader reader;
public MyBufferedReader(Reader reader) {
this.reader = reader;
}
public String readLine() throws IOException {
StringBuilder sb = new StringBuilder();
int ch = -1;
while ((ch = reader.read()) != -1) {
if (ch == '\r') {// 遇到换行符继续
continue;
} else if (ch == '\n') {// 遇到回车符表示读取完毕
return sb.toString();
} else {
sb.append((char) ch);
}
}
if (sb.length() != 0) {
return sb.toString();
}
return null;
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
reader.read(cbuf, off, len);
return 0;
}
@Override
public void close() throws IOException {
if (reader != null) {
reader.close();
}
}
}
在BufferedReader中有个直接子类LineNumberReader,LineNumberReader提供了特有的方法设置开始行号或获取每行行号:
public void setLineNumber(int lineNumber)// 设置开始行号
public int getLineNumber()// 获取每行行号
使用示例:
package com.dawndaybreak.ioexample;
import java.io.FileReader;
import java.io.LineNumberReader;
/**
*
* @author 通过LineNumberReader特有的方法,设置/获取行号
*
*/
public class LineNumberReaderDemo {
public static void main(String[] args) throws Exception {
LineNumberReader lineReader = new LineNumberReader(new FileReader(
"E:/demo.txt"));
lineReader.setLineNumber(9);// 设置开始行号
while (lineReader.readLine() != null) {
// 输出每一行行号
System.out.println(lineReader.getLineNumber());
}
lineReader.close();
}
}
1、当想对已有对象进行功能增强时,可定义类:将已有对象传入,基于已有对象的功能,并提供加强功能,那么自定义的该类称之为装饰类。例如:Java IO体系。
2、装饰类通常都会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
3、装饰和继承的区别:
1)装饰模式比继承要灵活。避免了继承体系的臃肿,且降低了类与类之间的关系。
2)装饰模式比继承要灵活。避免了继承体系的臃肿,且降低了类与类之间的关系。
3)从继承结构转为组合结构。
4)在定义类的时候,不要以继承为主;可通过装饰设计模式进行增强类功能。灵活性较强,当装饰类中的功能不适合,可再使用被装饰类的功能。
第三讲 字节流
一、概述
1、字节流和字符流的基本操作是相同的,但字节流还可以操作其他媒体文件。
2、由于媒体文件数据中都是以字节存储的,所以,字节流对象可直接对媒体文件的数据写入到文件中,而可以不用再进行刷流动作。
3、读写字节流:InputStream(输入流,用于读操作)、OutputStream(输出流,用于写操作)
4、为何不用进行刷流动作:因为字节流操作的是字节,即数据的最小单位,不需要像字符流一样要进行转换为字节。所以可直接将字节数据写入到指定文件中。
5、InputStream特有方法:
public int available();// 返回文件中的字节个数(即有效内容长度)
6、一般在文件较小时可用available方法来指定数组长度,从而省去循环判断。但是如果文件较大,此时数组长度过长,很有可能就造成内存溢出。
使用示例(copy图片):
package com.dawndaybreak.ioexample;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 复制图片,也可复制其他文件
*
* @author dawn
*
*/
public class CopyImage {
public static void main(String[] args) {
String filePath = "E:/img1.jpg";
String outputPath = "E:/img2.jpg";
String outputPathNext = "E:/img3.jpg";
getInstance().byByteArrayCopy(filePath, outputPath);
getInstance().byAvailableCopy(filePath, outputPathNext);
}
private InputStream is = null;
private OutputStream os = null;
public static CopyImage getInstance() {
return new CopyImage();
}
/**
* 使用available方法一次性读取所有内容,写入目的文件,当文件较大时,极有可能造成内存溢出
*
* @param filePath
* @param outputPath
*/
public void byAvailableCopy(String filePath, String outputPath) {
try {
initStream(filePath, outputPath);
// 一次读取所有字节内容,如果文件较大,极有可能会造成内存溢出
byte[] buffer = new byte[is.available()];
is.read(buffer);
os.write(buffer);
} catch (Exception e) {
} finally {
close();
}
}
private void initStream(String filePath, String outputPath)
throws FileNotFoundException {
is = new FileInputStream(filePath);
os = new FileOutputStream(outputPath);
}
/**
* 普通复制方法,通过字节数组复制
*
* @param filePath
* 目标文件路径
* @param outputPath
* 输出目标路径
*/
public void byByteArrayCopy(String filePath, String outputPath) {
try {
initStream(filePath, outputPath);
// 一次读取1024个字节
byte[] buffer = new byte[1024];
int len = -1;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
os.flush();
}
} catch (Exception e) {
} finally {
close();
}
}
private void close() {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
与字符流缓冲区一样,为了提高流的读写效率。
1、读写特点:
read():会将字节byte型值提升为int型值
write():会将int型强转为byte型,即保留二进制数的最后八位。
2、原理:将数据拷贝一部分,读取一部分,循环,直到数据全部读取完毕。
1)先从数据中抓取固定数组长度的字节,存入定义的数组中,再通过然后再通过read()方法读取数组中的元素,存入缓冲区。
2)循环这个动作,直到最后取出一组数据存入数组,可能数组并未填满,同样也取出包含的元素。
3)每次取出的时候,都有一个指针在移动,取到数组结尾就自动回到数组头部,这样指针在自增。
4)取出的时候,数组中的元素在减少,取出一个,就减少一个,直到减到0即元素取完。
5)当文件中的全部数据都被读取出时,read()方法就返回-1。
3、自定义读取字节流缓冲区
需求:根据字节流缓冲区的原理,自定义一个字节流缓冲区。
注意:
1、字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。
2、因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
3、所以,为了避免这种情况将读到的字节进行int类型的提升。并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。而在写入数据时,只写该int类型数据的最低8位。
4、byte类型的-1提升为int类型时还是-1。原因:因为在bit8个1前面补的全是1导致的。如果在bit8个1前面补0,即可以保留原字节数据不变,又可以避免-1的出现。这时将byte型数据&0xff即255即可。
自定义示例:
package com.dawndaybreak.ioexample;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 自定义字节缓冲,实现文件复制
*
* @author dawn
*
*/
public class MyBufferedInputStream extends InputStream {
public static void main(String[] args) {
MyBufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new MyBufferedInputStream(new FileInputStream("E:/img1.jpg"));
bos = new BufferedOutputStream(new FileOutputStream("E:/img2.jpg"));
int by = -1;
while ((by = bis.read()) != -1) {
bos.write(by);
}
} catch (Exception e) {
} finally {
try {
if (bis != null) {
bis.close();
}
if (bos != null) {
bos.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private InputStream is;
private byte[] buffer = new byte[1024];
private int count = 0, pos = 0;
public MyBufferedInputStream(InputStream is) {
this.is = is;
}
@Override
public int read() throws IOException {
if (count == 0) {// 第一次调用read方法
count = is.read(buffer);
if (count < 0) {
return -1;
}
// 初始化指针
pos = 0;
byte b = buffer[pos];
count--;// 每读取一个字节,表示数组中的字节数就少一个
pos++;// 指针+1,下次放访问buffer数组,指向下个位置
// 将返回的byte数据提升为int类型,字节数增加,且高24位被补1,原字节数据改变。
// 通过&255,主动将byte类型提升为int类型,提高24位补0,原字节数据不变。
// 在输出字节流写入数据时,只写该int数据的最低8位。
return b & 255;
} else if (count > 0) {// 不是第一次调用,且buffer中数据没有读取完时
byte b = buffer[pos];
count--;
pos++;
return b & 0xff;
}
return -1;
}
@Override
public void close() throws IOException {
if (is != null) {
is.close();
}
}
}
第四讲 操作流规律
一、键盘录入
1、标准输入输出流
System.in:对应的标准输入设备:键盘;对应的类型:InputStream。
System.out:对应的标准输出设备:控制台;对应的类型:PrintStream,是OutputStream的子类FileOutputStream的子类。
2、整行录入
当使用输入流进行键盘录入时,只能一个字节一个字节进行录入。为了提高效率,可以自定义一个数组进行存储。当一行录入完毕,再将一行数据进行显示。这种整行录入的方式,和字符流读一行数据的原理是一样的。也就是readLine()。
那么能不能直接使用readLine()来完成键盘录入的一行数据的读取呢?readLine()是字符流BufferedReader类中方法。而键盘录入的read()是字节流InputStream的方法。
那么能不能将字节流转成字符流再使用字符流缓冲区的readLine()呢?这就需要用到转换流了。
3、转换流
3.1、转换流的由来:
1)字符流与字节流直接的桥梁;
2)方便了字符流与字节流之间的操作;
3)字节流中的数据都是字符时,转成字符流操作更高效。
3.2、InputStreamReader将字节流通向字符流
1)获取键盘录入对象
InputStream in = System.in;
2)将字节流对象转成字符流对象,使用转换流
InputStreamReader isr = new InputStreamReader(in);
3)为了提高效率,使用BufferedReader将字符串进行缓冲区技术高效操作。
BufferedReader br = new BufferedReader(isr);
4)上面三个步骤的合并写法
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
3.3、OutputStreamWriter字符流通向字节流
字符流通向字节流:录入的是字符,存到硬盘上的是字节。步骤和InputStreamReader转换流一样。
使用示例:
package com.dawndaybreak.ioexample;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
/**
* 将键盘录入的数据显示在控制台,当输入0时,退出程序
*
* @author xuHaiLiang
*
*/
public class TransformStreamDemo {
public static void main(String[] args) throws IOException {
// 将键盘录入,字节流通向字符流
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 控制输出,字符流通向字节流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
System.out));
String s = null;
while ((s = br.readLine()) != null) {
if ("0".equals(s)) {
break;
}
bw.write(s);
bw.newLine();
bw.flush();
}
br.close();
bw.close();
}
}
示例(将键盘录入写入文件):
public static void main(String[] args) throws IOException {
// 将键盘录入,字节流通向字符流
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 控制输出,字符流通向字节流
// BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
// System.out));
// 将键盘录入内容存储到文件
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("E:/demo.txt")));
String s = null;
while ((s = br.readLine()) != null) {
if ("0".equals(s)) {
break;
}
bw.write(s);
bw.newLine();
bw.flush();
}
br.close();
bw.close();
}
public static void main(String[] args) throws IOException {
// 将键盘录入,字节流通向字符流
// BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("E:/demo.txt")));
// 控制输出,字符流通向字节流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
System.out));
// 将键盘录入内容存储到文件
// BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("E:/demo.txt")));
String s = null;
while ((s = br.readLine()) != null) {
if ("0".equals(s)) {
break;
}
bw.write(s);
bw.newLine();
bw.flush();
}
br.close();
bw.close();
}
package com.dawndaybreak.ioexample;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Log {
public static void main(String[] args) {
try {
System.out.println(Integer.parseInt("dd"));
} catch (Exception e) {
try {
PrintStream pw = new PrintStream("E:/log.log");
System.setOut(pw);
System.out.println(new SimpleDateFormat("yyyy-MM-dd")
.format(new Date()));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
e.printStackTrace(System.out);
}
}
}
public static void main(String[] args) throws FileNotFoundException {
Properties p = System.getProperties();
p.list(new PrintStream("E:/systemProperties.txt"));
}
System.setIn(newFileInputStream("demo.txt"));//将源改成文件demo.txt
System.setOut(newFileOutputStream("demo2.txt"));//将目的改成文件demo2.txt
流的基本应用小结:
1)流是用来处理数据的。
2)处理数据时,一定要先明确数据源,与数据目的地(数据汇)。
3)数据源可以是文件,可以是键盘。
4)数据目的地可以是文件、显示器或者其他设备。
5)而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理.转换处理等。