java基础知识----IO篇
写在前面:本文章基本覆盖了java IO的所有内容。java新IO没有涉及。文章依然以样例为主,由于解说内容的java书非常多了,我觉的学以致用才是真。代码是写出来的,不是看出来的。
最后欢迎大家提出意见和建议。
【案例1】创建一个新文件
1
2
3
4
5
6
7
8
9
10
11
|
import java.io.*; class hello{ public static void main(String[] args) { File f= new File( "D:\\hello.txt" ); try { f.createNewFile(); } catch (Exception e) { e.printStackTrace(); } } } |
【执行结果】:
程序执行之后。在d盘下会有一个名字为hello.txt的文件。
【案例2】File类的两个常量
1
2
3
4
5
6
7
|
import java.io.*; class hello{ public static void main(String[] args) { System.out.println(File.separator); System.out.println(File.pathSeparator); } } |
【执行结果】:
\
;
此处多说几句:有些同学可能觉得。我直接在windows下使用\进行切割不行吗?当然是能够的。
可是在linux下就不是\了。
所以,要想使得我们的代码跨平台。更加健壮,所以,大家都採用这两个常量吧。事实上也多写不了几行。
呵呵、
如今我们使用File类中的常量改写上面的代码:
1
2
3
4
5
6
7
8
9
10
11
12
|
import java.io.*; class hello{ public static void main(String[] args) { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); try { f.createNewFile(); } catch (Exception e) { e.printStackTrace(); } } } |
你看,没有多写多少吧,呵呵。所以建议使用File类中的常量。
删除一个文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/** * 删除一个文件 * */ import java.io.*; class hello{ public static void main(String[] args) { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); if (f.exists()){ f.delete(); } else { System.out.println( "文件不存在" ); } } } |
创建一个目录
1
2
3
4
5
6
7
8
9
10
11
|
/** * 创建一个目录 * */ import java.io.*; class hello{ public static void main(String[] args) { String fileName= "D:" +File.separator+ "hello" ; File f= new File(fileName); f.mkdir(); } } |
【执行结果】:
D盘下多了一个hello目录
列出指定文件夹的所有文件(包含隐藏文件):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/** * 使用list列出指定文件夹的所有文件 * */ import java.io.*; class hello{ public static void main(String[] args) { String fileName= "D:" +File.separator; File f= new File(fileName); String[] str=f.list(); for ( int i =
0 ; i < str.length; i++) { System.out.println(str[i]); } } } |
【执行结果】:
$RECYCLE.BIN
360
360Downloads
360Rec
360SoftMove
Config.Msi
da
Downloads
DriversBackup
eclipse
java web整合开发和项目实战
Lenovo
MSOCache
Program
Program Files
python
RECYGLER.{8F92DA15-A229-A4D5-B5CE-5280C8B89C19}
System Volume Information
Tomcat6
var
vod_cache_data
新建目录
(你的执行结果应该和这个不一样的。呵呵)
可是使用list返回的是String数组,。
并且列出的不是完整路径,假设想列出完整路径的话。须要使用listFiles.他返回的是File的数组
列出指定文件夹的所有文件(包含隐藏文件):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/** * 使用listFiles列出指定文件夹的所有文件 * listFiles输出的是完整路径 * */ import java.io.*; class hello{ public static void main(String[] args) { String fileName= "D:" +File.separator; File f= new File(fileName); File[] str=f.listFiles(); for ( int i =
0 ; i < str.length; i++) { System.out.println(str[i]); } } } |
【执行结果】:
D:\$RECYCLE.BIN
D:\360
D:\360Downloads
D:\360Rec
D:\360SoftMove
D:\Config.Msi
D:\da
D:\Downloads
D:\DriversBackup
D:\eclipse
D:\java web整合开发和项目实战
D:\Lenovo
D:\MSOCache
D:\Program
D:\Program Files
D:\python
D:\RECYGLER.{8F92DA15-A229-A4D5-B5CE-5280C8B89C19}
D:\System Volume Information
D:\Tomcat6
D:\var
D:\vod_cache_data
D:\新建目录
通过比較能够指定,使用listFiles更加方便、
推断一个指定的路径是否为文件夹
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/** * 使用isDirectory推断一个指定的路径是否为文件夹 * */ import java.io.*; class hello{ public static void main(String[] args) { String fileName= "D:" +File.separator; File f= new File(fileName); if (f.isDirectory()){ System.out.println( "YES" ); } else { System.out.println( "NO" ); } } } |
【执行结果】:YES
搜索指定文件夹的所有内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/** * 列出指定文件夹的所有内容 * */ import java.io.*; class hello{ public static void main(String[] args) { String fileName= "D:" +File.separator; File f= new File(fileName); print(f); } public static void print(File f){ if (f!= null ){ if (f.isDirectory()){ File[] fileArray=f.listFiles(); if (fileArray!= null ){ for ( int i =
0 ; i < fileArray.length; i++) { //递归调用 print(fileArray[i]); } } } else { System.out.println(f); } } } } |
【执行结果】:
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\framepages\web4welcome_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\help_005fhome_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\help_005fhome_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\home_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\home_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\index_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\index_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\login_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\login_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\modify_005fuser_005finfo_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\modify_005fuser_005finfo_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\register_005fnotify_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\register_005fnotify_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\sign_005fup_jsp.class
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\sign_005fup_jsp.java
D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\transit_jsp.class
……
【使用RandomAccessFile写入文件】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/** * 使用RandomAccessFile写入文件 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); RandomAccessFile demo= new RandomAccessFile(f, "rw" ); demo.writeBytes( "asdsad" ); demo.writeInt( 12 ); demo.writeBoolean( true ); demo.writeChar( 'A' ); demo.writeFloat( 1 .21f); demo.writeDouble( 12.123 ); demo.close(); } } |
假设你此时打开hello。txt查看的话,会发现那是乱码。
字节流
【向文件里写入字符串】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/** * 字节流 * 向文件里写入字符串 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); OutputStream out = new FileOutputStream(f); String str= "你好" ; byte [] b=str.getBytes(); out.write(b); out.close(); } } |
查看hello.txt会看到“你好”
当然也能够一个字节一个字节的写。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/** * 字节流 * 向文件里一个字节一个字节的写入字符串 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); OutputStream out = new FileOutputStream(f); String str= "你好" ; byte [] b=str.getBytes(); for ( int i =
0 ; i < b.length; i++) { out.write(b[i]); } out.close(); } } |
结果还是:“你好”
向文件里追加新内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/** * 字节流 * 向文件里追加新内容: * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); OutputStream out = new FileOutputStream(f, true ); String str= "Rollen" ; //String str="\r\nRollen"; 能够换行 byte [] b=str.getBytes(); for ( int i =
0 ; i < b.length; i++) { out.write(b[i]); } out.close(); } } |
【执行结果】:
你好Rollen
【读取文件内容】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/** * 字节流 * 读文件内容 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); InputStream in= new FileInputStream(f); byte [] b= new byte [ 1024 ]; in.read(b); in.close(); System.out.println( new String(b)); } } |
【执行结果】
你好Rollen
Rollen_
可是这个样例读取出来会有大量的空格。我们能够利用in.read(b);的返回值来设计程序。
例如以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 字节流 * 读文件内容 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); InputStream in= new FileInputStream(f); byte [] b= new byte [ 1024 ]; int len=in.read(b); in.close(); System.out.println( "读入长度为:" +len); System.out.println( new String(b, 0 ,len)); } } |
【执行结果】:
读入长度为:18
你好Rollen
Rollen
读者观察上面的样例能够看出,我们预先申请了一个指定大小的空间,可是有时候这个空间可能太小。有时候可能太大,我们须要准确的大小,这样节省空间,那么我们能够这样干:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 字节流 * 读文件内容,节省空间 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); InputStream in= new FileInputStream(f); byte [] b= new byte [( int )f.length()]; in.read(b); System.out.println( "文件长度为:" +f.length()); in.close(); System.out.println( new String(b)); } } |
文件长度为:18
你好Rollen
Rollen
将上面的样例改为一个一个读:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/** * 字节流 * 读文件内容,节省空间 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); InputStream in= new FileInputStream(f); byte [] b= new byte [( int )f.length()]; for ( int i =
0 ; i < b.length; i++) { b[i]=( byte )in.read(); } in.close(); System.out.println( new String(b)); } } |
输出的结果和上面的一样。
细心的读者可能会发现。上面的几个样例都是在知道文件的内容多大,然后才展开的。有时候我们不知道文件有多大,这样的情况下,我们须要推断是否独到文件的末尾。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/** * 字节流 *读文件 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); InputStream in= new FileInputStream(f); byte [] b= new byte [ 1024 ]; int count = 0 ; int temp= 0 ; while ((temp=in.read())!=(- 1 )){ b[count++]=( byte )temp; } in.close(); System.out.println( new String(b)); } } |
【执行结果】
你好Rollen
Rollen_
提醒一下。当独到文件末尾的时候会返回-1.正常情况下是不会返回-1的
字符流
【向文件里写入数据】
如今我们使用字符流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/** * 字符流 * 写入数据 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); Writer out = new FileWriter(f); String str= "hello" ; out.write(str); out.close(); } } |
当你打开hello。txt的时候。会看到hello
事实上这个样例上之前的样例没什么差别,仅仅是你能够直接输入字符串。而不须要你将字符串转化为字节数组。
当你假设想问文件里追加内容的时候。能够使用将上面的声明out的哪一行换为:
Writer out =new FileWriter(f,true);
这样,当你执行程序的时候。会发现文件内容变为:
hellohello假设想在文件里换行的话,须要使用“\r\n”
比方将str变为String str="\r\nhello";
这样文件追加的str的内容就会换行了。
从文件里读内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 字符流 * 从文件里读出内容 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); char [] ch= new char [ 100 ]; Reader read= new FileReader(f); int count=read.read(ch); read.close(); System.out.println( "读入的长度为:" +count); System.out.println( "内容为" + new String(ch, 0 ,count)); } } |
【执行结果】:
读入的长度为:17
内容为hellohello
hello
当然最好採用循环读取的方式。由于我们有时候不知道文件究竟有多大。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/** * 字符流 * 从文件里读出内容 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "D:" +File.separator+ "hello.txt" ; File f= new File(fileName); char [] ch= new char [ 100 ]; Reader read= new FileReader(f); int temp= 0 ; int count= 0 ; while ((temp=read.read())!=(- 1 )){ ch[count++]=( char )temp; } read.close(); System.out.println( "内容为" + new String(ch, 0 ,count)); } } |
执行结果:
内容为hellohello
hello
关于字节流和字符流的差别
实际上字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的,可是字符流在操作的 时候下后是会用到缓冲区的,是通过缓冲区来操作文件的。
读者能够试着将上面的字节流和字符流的程序的最后一行关闭文件的代码凝视掉,然后执行程序看看。你就会发现使用字节流的话,文件里已经存在内容。可是使用字符流的时候,文件里还是没有内容的。这个时候就要刷新缓冲区。
使用字节流好还是字符流好呢?
答案是字节流。
首先由于硬盘上的全部文件都是以字节的形式进行传输或者保存的。包含图片等内容。可是字符仅仅是在内存中才会形成的。所以在开发中,字节流使用广泛。
文件的复制
事实上DOS下就有一个文件复制功能,比方我们想把d盘以下的hello.txt文件拷贝到d盘以下的rollen.txt文件里,那么我们就能够使用以下的命令:
copy d:\hello.txt d:\rollen.txt
执行之后你会在d盘中看见hello.txt.,而且两个文件的内容是一样的,(这是屁话)
以下我们使用程序来拷贝文件吧。
基本思路还是从一个文件里读入内容。边读边写入还有一个文件。就是这么简单。、
首先编写以下的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
/** * 文件的复制 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { if (args.length!= 2 ){ System.out.println( "命令行參数输入有误,请检查" ); System.exit( 1 ); } File file1= new File(args[ 0 ]); File file2= new File(args[ 1 ]); if (!file1.exists()){ System.out.println( "被复制的文件不存在" ); System.exit( 1 ); } InputStream input= new FileInputStream(file1); OutputStream output= new FileOutputStream(file2); if ((input!= null )&&(output!= null )){ int temp= 0 ; while ((temp=input.read())!=(- 1 )){ output.write(temp); } } input.close(); output.close(); } } |
然后在命令行以下
javac hello.java
java hello d:\hello.txt d:\rollen.txt
如今你就会在d盘看到rollen。txt了。
OutputStreramWriter 和InputStreamReader类
整个IO类中除了字节流和字符流还包含字节和字符转换流。
OutputStreramWriter将输出的字符流转化为字节流
InputStreamReader将输入的字节流转换为字符流
可是无论怎样操作。最后都是以字节的形式保存在文件里的。
将字节输出流转化为字符输出流
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/** * 将字节输出流转化为字符输出流 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "d:" +File.separator+ "hello.txt" ; File file= new File(fileName); Writer out= new OutputStreamWriter( new FileOutputStream(file)); out.write( "hello" ); out.close(); } } |
执行结果:文件里内容为:hello
将字节输入流变为字符输入流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/** * 将字节输入流变为字符输入流 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String fileName= "d:" +File.separator+ "hello.txt" ; File file= new File(fileName); Reader read= new InputStreamReader( new FileInputStream(file)); char [] b= new char [ 100 ]; int len=read.read(b); System.out.println( new String(b, 0 ,len)); read.close(); } } |
【执行结果】:hello
前面列举的输出输入都是以文件进行的,如今我们以内容为输出输入目的地,使用内存操作流
ByteArrayInputStream 主要将内容写入内容
ByteArrayOutputStream 主要将内容从内存输出
使用内存操作流将一个大写字母转化为小写字母
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/** * 使用内存操作流将一个大写字母转化为小写字母 * */ import java.io.*; class hello{ public static void main(String[] args)
throws IOException { String str= "ROLLENHOLT" ; ByteArrayInputStream input= new ByteArrayInputStream(str.getBytes()); ByteArrayOutputStream output= new ByteArrayOutputStream(); int temp= 0 ; while ((temp=input.read())!=- 1 ){ char ch=( char )temp; output.write(Character.toLowerCase(ch)); } String outStr=output.toString(); input.close(); output.close(); System.out.println(outStr); } } |
【执行结果】:
rollenholt
内容操作流一般使用来生成一些暂时信息採用的,这样能够避免删除的麻烦。
管道流
管道流主要能够进行两个线程之间的通信。
PipedOutputStream 管道输出流
PipedInputStream 管道输入流
验证管道流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
/** * 验证管道流 * */ import java.io.*; /** * 消息发送类 * */ class Send implements Runnable{ private PipedOutputStream out= null ; public Send() { out= new PipedOutputStream(); } public PipedOutputStream getOut(){ return this .out; } public void run(){ String message= "hello , Rollen" ; try { out.write(message.getBytes()); } catch (Exception e) { e.printStackTrace(); } try { out.close(); } catch (Exception e) { e.printStackTrace(); } } } /** * 接受消息类 * */ class Recive
implements Runnable{ private PipedInputStream input= null ; public Recive(){ this .input= new PipedInputStream(); } public PipedInputStream getInput(){ return this .input; } public void run(){ byte [] b= new byte [ 1000 ]; int len= 0 ; try { len= this .input.read(b); } catch (Exception e) { e.printStackTrace(); } try { input.close(); } catch (Exception e) { e.printStackTrace(); } System.out.println( "接受的内容为 " +( new String(b, 0 ,len))); } } /** * 測试类 * */ class hello{ public static void main(String[] args)
throws IOException { Send send= new Send(); Recive recive= new Recive(); try { //管道连接 send.getOut().connect(recive.getInput()); } catch (Exception e) { e.printStackTrace(); } new Thread(send).start(); new Thread(recive).start(); } } |
【执行结果】:
接受的内容为 hello , Rollen
打印流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/** * 使用PrintStream进行输出 * */ import java.io.*; class hello { public static void main(String[] args)
throws IOException { PrintStream print = new PrintStream( new FileOutputStream( new File( "d:" + File.separator + "hello.txt" ))); print.println( true ); print.println( "Rollen" ); print.close(); } } |
【执行结果】:
true
Rollen
当然也能够格式化输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/** * 使用PrintStream进行输出 * 并进行格式化 * */ import java.io.*; class hello { public static void main(String[] args)
throws IOException { PrintStream print = new PrintStream( new FileOutputStream( new File( "d:" + File.separator + "hello.txt" ))); String name= "Rollen" ; int age= 20 ; print.printf( "姓名:%s. 年龄:%d." ,name,age); print.close(); } } |
【执行结果】:
姓名:Rollen. 年龄:20.
使用OutputStream向屏幕上输出内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/** * 使用OutputStream向屏幕上输出内容
* */ import java.io.*; class hello { public static void main(String[] args)
throws IOException { OutputStream out=System.out; try { out.write( "hello" .getBytes()); } catch (Exception e) { e.printStackTrace(); } try { out.close(); } catch (Exception e) { e.printStackTrace(); } } } |
【执行结果】:
hello
输入输出重定向
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; /** * 为System.out.println()重定向输出 * */ public class systemDemo{ public static void main(String[] args){ // 此刻直接输出到屏幕 System.out.println( "hello" ); File file = new File( "d:" + File.separator +
"hello.txt" ); try { System.setOut( new PrintStream( new FileOutputStream(file))); } catch (FileNotFoundException e){ e.printStackTrace(); } System.out.println( "这些内容在文件里才干看到哦!" ); } } |
【执行结果】:
eclipse的控制台输出的是hello。然后当我们查看d盘以下的hello.txt文件的时候,会在里面看到:这些内容在文件里才干看到哦!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; /** * System.err重定向 这个样例也提示我们能够使用这样的方法保存错误信息 * */ public class systemErr{ public static void main(String[] args){ File file = new File( "d:" + File.separator +
"hello.txt" ); System.err.println( "这些在控制台输出" ); try { System.setErr( new PrintStream( new FileOutputStream(file))); } catch (FileNotFoundException e){ e.printStackTrace(); } System.err.println( "这些在文件里才干看到哦!" ); } } |
【执行结果】:
你会在eclipse的控制台看到红色的输出:“这些在控制台输出”,然后在d盘以下的hello.txt中会看到:这些在文件里才干看到哦!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; /** * System.in重定向 * */ public class systemIn{ public static void main(String[] args){ File file = new File( "d:" + File.separator +
"hello.txt" ); if (!file.exists()){ return ; } else { try { System.setIn( new FileInputStream(file)); } catch (FileNotFoundException e){ e.printStackTrace(); } byte [] bytes =
new byte [ 1024 ]; int len =
0 ; try { len = System.in.read(bytes); } catch (IOException e){ e.printStackTrace(); } System.out.println( "读入的内容为:" +
new String(bytes,
0 , len)); } } } |
【执行结果】:
前提是我的d盘以下的hello.txt中的内容是:“这些文件里的内容哦!”,然后执行程序,输出的结果为:读入的内容为:这些文件里的内容哦!
BufferedReader的小样例
注意: BufferedReader仅仅能接受字符流的缓冲区。由于每个中文须要占领两个字节。所以须要将System.in这个字节输入流变为字符输入流。採用:
BufferedReader buf = new BufferedReader( new InputStreamReader(System.in)); |
以下给一个实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * 使用缓冲区从键盘上读入内容 * */ public class BufferedReaderDemo{ public static void main(String[] args){ BufferedReader buf = new BufferedReader( new InputStreamReader(System.in)); String str = null ; System.out.println( "请输入内容" ); try { str = buf.readLine(); } catch (IOException e){ e.printStackTrace(); } System.out.println( "你输入的内容是:" + str); } } |
执行结果:
请输入内容
dasdas
你输入的内容是:dasdas
Scanner类
事实上我们比較经常使用的是採用Scanner类来进行数据输入,以下来给一个Scanner的样例吧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import java.util.Scanner; /** * Scanner的小样例,从键盘读数据 * */ public class ScannerDemo{ public static void main(String[] args){ Scanner sca = new Scanner(System.in); // 读一个整数 int temp = sca.nextInt(); System.out.println(temp); //读取浮点数 float flo=sca.nextFloat(); System.out.println(flo); //读取字符 //...等等的,都是一些太基础的,就不师范了。 } } |
事实上Scanner能够接受不论什么的输入流
以下给一个使用Scanner类从文件里读出内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; /** * Scanner的小样例,从文件里读内容 * */ public class ScannerDemo{ public static void main(String[] args){ File file = new File( "d:" + File.separator +
"hello.txt" ); Scanner sca = null ; try { sca = new Scanner(file); } catch (FileNotFoundException e){ e.printStackTrace(); } String str = sca.next(); System.out.println( "从文件里读取的内容是:" + str); } } |
【执行结果】:
从文件里读取的内容是:这些文件里的内容哦。
数据操作流DataOutputStream、DataInputStream类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; public class DataOutputStreamDemo{ public static void main(String[] args)
throws IOException{ File file = new File( "d:" + File.separator +
"hello.txt" ); char [] ch = {
'A' , 'B' ,
'C' }; DataOutputStream out = null ; out = new DataOutputStream( new FileOutputStream(file)); for ( char temp : ch){ out.writeChar(temp); } out.close(); } } |
A B C
如今我们在上面样例的基础上,使用DataInputStream读出内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class DataOutputStreamDemo{ public static void main(String[] args)
throws IOException{ File file = new File( "d:" + File.separator +
"hello.txt" ); DataInputStream input = new DataInputStream( new FileInputStream(file)); char [] ch =
new char [ 10 ]; int count =
0 ; char temp; while ((temp = input.readChar()) !=
'C' ){ ch[count++] = temp; } System.out.println(ch); } } |
【执行结果】:
AB
合并流 SequenceInputStream
SequenceInputStream主要用来将2个流合并在一起,比方将两个txt中的内容合并为另外一个txt。
以下给出一个实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.SequenceInputStream; /** * 将两个文本文件合并为另外一个文本文件 * */ public class SequenceInputStreamDemo{ public static void main(String[] args)
throws IOException{ File file1 = new File( "d:" + File.separator +
"hello1.txt" ); File file2 = new File( "d:" + File.separator +
"hello2.txt" ); File file3 = new File( "d:" + File.separator +
"hello.txt" ); InputStream input1 = new FileInputStream(file1); InputStream input2 = new FileInputStream(file2); OutputStream output = new FileOutputStream(file3); // 合并流 SequenceInputStream sis = new SequenceInputStream(input1, input2); int temp =
0 ; while ((temp = sis.read()) != - 1 ){ output.write(temp); } input1.close(); input2.close(); output.close(); sis.close(); } } |
【执行结果】
结果会在hello.txt文件里包括hello1.txt和hello2.txt文件里的内容。
文件压缩 ZipOutputStream类
先举一个压缩单个文件的样例吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipOutputStreamDemo1{ public static void main(String[] args)
throws IOException{ File file = new File( "d:" + File.separator +
"hello.txt" ); File zipFile = new File( "d:" + File.separator +
"hello.zip" ); InputStream input = new FileInputStream(file); ZipOutputStream zipOut = new ZipOutputStream( new FileOutputStream( zipFile)); zipOut.putNextEntry( new ZipEntry(file.getName())); // 设置凝视 zipOut.setComment( "hello" ); int temp =
0 ; while ((temp = input.read()) != - 1 ){ zipOut.write(temp); } input.close(); zipOut.close(); } } |
【执行结果】
执行结果之前,我创建了一个hello.txt的文件,原本大小56个字节。可是压缩之后产生hello.zip之后,竟然变成了175个字节,有点搞不懂。
只是结果肯定是正确的,我仅仅是提出我的一个疑问而已。
上面的这个样例測试的是压缩单个文件,以下的们来看看怎样压缩多个文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * 一次性压缩多个文件 * */ public class ZipOutputStreamDemo2{ public static void main(String[] args)
throws IOException{ // 要被压缩的目录 File file = new File( "d:" + File.separator +
"temp" ); File zipFile = new File( "d:" + File.separator +
"zipFile.zip" ); InputStream input = null ; ZipOutputStream zipOut = new ZipOutputStream( new FileOutputStream( zipFile)); zipOut.setComment( "hello" ); if (file.isDirectory()){ File[] files = file.listFiles(); for ( int i =
0 ; i < files.length; ++i){ input = new FileInputStream(files[i]); zipOut.putNextEntry( new ZipEntry(file.getName() + File.separator + files[i].getName())); int temp =
0 ; while ((temp = input.read()) != - 1 ){ zipOut.write(temp); } input.close(); } } zipOut.close(); } } |
【执行结果】
先看看要被压缩的文件吧:
接下来看看压缩之后的:
大家自然想到,既然能压缩。自然能解压缩,在谈解压缩之前。我们会用到一个ZipFile类,先给一个这个样例吧。
java中的每个压缩文件都是能够使用ZipFile来进行表示的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import java.io.File; import java.io.IOException; import java.util.zip.ZipFile; /** * ZipFile演示 * */ public class ZipFileDemo{ public static void main(String[] args)
throws IOException{ File file = new File( "d:" + File.separator +
"hello.zip" ); ZipFile zipFile = new ZipFile(file); System.out.println( "压缩文件的名称为:" + zipFile.getName()); } } |
【执行结果】:
压缩文件的名称为:d:\hello.zip
如今我们呢是时候来看看怎样加压缩文件了,和之前一样,先让我们来解压单个压缩文件(也就是压缩文件里仅仅有一个文件的情况)。我们採用前面的样例产生的压缩文件hello.zip
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** * 解压缩文件(压缩文件里仅仅有一个文件的情况) * */ public class ZipFileDemo2{ public static void main(String[] args)
throws IOException{ File file = new File( "d:" + File.separator +
"hello.zip" ); File outFile = new File( "d:" + File.separator +
"unZipFile.txt" ); ZipFile zipFile = new ZipFile(file); ZipEntry entry = zipFile.getEntry( "hello.txt" ); InputStream input = zipFile.getInputStream(entry); OutputStream output = new FileOutputStream(outFile); int temp =
0 ; while ((temp = input.read()) != - 1 ){ output.write(temp); } input.close(); output.close(); } } |
【执行结果】:
解压缩之前:
这个压缩文件还是175字节
解压之后产生:
又回到了56字节。表示郁闷。
如今让我们来解压一个压缩文件里包括多个文件的情况吧
ZipInputStream类
当我们须要解压缩多个文件的时候,ZipEntry就无法使用了。假设想操作更加复杂的压缩文件。我们就必须使用ZipInputStream类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; /** * 解压缩一个压缩文件里包括多个文件的情况 * */ public class ZipFileDemo3{ public static void main(String[] args)
throws IOException{ File file = new File( "d:" + File.separator +
"zipFile.zip" ); File outFile = null ; ZipFile zipFile = new ZipFile(file); ZipInputStream zipInput = new ZipInputStream( new FileInputStream(file)); ZipEntry entry = null ; InputStream input = null ; OutputStream output = null ; while ((entry = zipInput.getNextEntry()) !=
null ){ System.out.println( "解压缩" + entry.getName() +
"文件" ); outFile = new File( "d:" + File.separator + entry.getName()); if (!outFile.getParentFile().exists()){ outFile.getParentFile().mkdir(); } if (!outFile.exists()){ outFile.createNewFile(); } input = zipFile.getInputStream(entry); output = new FileOutputStream(outFile); int temp =
0 ; while ((temp = input.read()) != - 1 ){ output.write(temp); } input.close(); output.close(); } } } |
【执行结果】:
被解压的文件:
解压之后再D盘下会出现一个temp目录,里面内容:
PushBackInputStream回退流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.PushbackInputStream; /** * 回退流操作 * */ public class PushBackInputStreamDemo{ public static void main(String[] args)
throws IOException{ String str = "hello,rollenholt" ; PushbackInputStream push = null ; ByteArrayInputStream bat = null ; bat = new ByteArrayInputStream(str.getBytes()); push = new PushbackInputStream(bat); int temp =
0 ; while ((temp = push.read()) != - 1 ){ if (temp ==
',' ){ push.unread(temp); temp = push.read(); System.out.print( "(回退" + ( char ) temp +
") " ); } else { System.out.print(( char ) temp); } } } } |
【执行结果】:
hello(回退,) rollenholt
1
2
3
4
5
6
7
8
|
/** * 取得本地的默认编码 * */ public class CharSetDemo{ public static void main(String[] args){ System.out.println( "系统默认编码为:" + System.getProperty( "file.encoding" )); } } |
【执行结果】:
系统默认编码为:GBK
乱码的产生:
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; /** * 乱码的产生 * */ public class CharSetDemo2{ public static void main(String[] args)
throws IOException{ File file = new File( "d:" + File.separator +
"hello.txt" ); OutputStream out = new FileOutputStream(file); byte [] bytes =
"你好" .getBytes( "ISO8859-1" ); out.write(bytes); out.close(); } } |
【执行结果】:
?
?
普通情况下产生乱码,都是因为编码不一致的问题。
对象的序列化
对象序列化就是把一个对象变为二进制数据流的一种方法。
一个类要想被序列化,即可必须实现java.io.Serializable接口。尽管这个接口中没有不论什么方法,就如同之前的cloneable接口一样。实现了这个接口之后。就表示这个类具有被序列化的能力。
先让我们实现一个具有序列化能力的类吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
import java.io.*; /** * 实现具有序列化能力的类 * */ public class SerializableDemo
implements Serializable{ public SerializableDemo(){ } public SerializableDemo(String name,
int age){ this .name=name; this .age=age; } @Override public String toString(){ return "姓名:" +name+ " 年龄:" +age; } private String name; private int age; } |
这个类就具有实现序列化能力。
在继续将序列化之前,先将一下ObjectInputStream和ObjectOutputStream这两个类
先给一个ObjectOutputStream的样例吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
import java.io.Serializable; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; /** * 实现具有序列化能力的类 * */ public class Person
implements Serializable{ public Person(){ } public Person(String name,
int age){ this .name = name; this .age = age; } @Override public String toString(){ return "姓名:" + name +
" 年龄:" + age; } private String name; private int age; } /** * 示范ObjectOutputStream * */ public class ObjectOutputStreamDemo{ public static void main(String[] args)
throws IOException{ File file = new File( "d:" + File.separator +
"hello.txt" ); ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream( file)); oos.writeObject( new Person( "rollen" ,
20 )); oos.close(); } } |
【执行结果】:
当我们查看产生的hello.txt的时候。看到的是乱码,呵呵。由于是二进制文件。
尽管我们不能直接查看里面的内容。可是我们能够使用ObjectInputStream类查看:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import java.io.File; import java.io.FileInputStream; import java.io.ObjectInputStream; /** * ObjectInputStream示范 * */ public class ObjectInputStreamDemo{ public static void main(String[] args)
throws Exception{ File file = new File( "d:" + File.separator +
"hello.txt" ); ObjectInputStream input = new ObjectInputStream( new FileInputStream( file)); Object obj = input.readObject(); input.close(); System.out.println(obj); } } |
【执行结果】
姓名:rollen 年龄:20
究竟序列化什么内容呢?
事实上仅仅有属性会被序列化。
Externalizable接口
被Serializable接口声明的类的对象的属性都将被序列化,可是假设想自己定义序列化的内容的时候,就须要实现Externalizable接口。
当一个类要使用Externalizable这个接口的时候,这个类中必需要有一个无參的构造函数,假设没有的话,在构造的时候会产生异常。这是由于在反序列话的时候会默认调用无參的构造函数。
如今我们来演示一下序列化和反序列话:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
package IO; import java.io.Externalizable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; /** * 序列化和反序列化的操作 * */ public class ExternalizableDemo{ public static void main(String[] args)
throws Exception{ ser(); // 序列化 dser(); // 反序列话 } public static void ser()
throws Exception{ File file = new File( "d:" + File.separator +
"hello.txt" ); ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream( file)); out.writeObject( new Person( "rollen" ,
20 )); out.close(); } public static void dser()
throws Exception{ File file = new File( "d:" + File.separator +
"hello.txt" ); ObjectInputStream input = new ObjectInputStream( new FileInputStream( file)); Object obj = input.readObject(); input.close(); System.out.println(obj); } } class Person
implements Externalizable{ public Person(){ } public Person(String name,
int age){ this .name = name; this .age = age; } @Override public String toString(){ return "姓名:" + name +
" 年龄:" + age; } // 复写这种方法,依据须要能够保存的属性或者详细内容,在序列化的时候使用 @Override public void writeExternal(ObjectOutput out)
throws IOException{ out.writeObject( this .name); out.writeInt(age); } // 复写这种方法。依据须要读取内容 反序列话的时候须要 @Override public void readExternal(ObjectInput in)
throws IOException, ClassNotFoundException{ this .name = (String) in.readObject(); this .age = in.readInt(); } private String name; private int age; } |
【执行结果】:
姓名:rollen 年龄:20
本例中,我们将所有的属性都保留了下来,
Serializable接口实现的操作事实上是吧一个对象中的所有属性进行序列化,当然也能够使用我们上使用是Externalizable接口以实现部分属性的序列化。可是这种操作比較麻烦,
当我们使用Serializable接口实现序列化操作的时候,假设一个对象的某一个属性不想被序列化保存下来,那么我们能够使用transientkeyword进行说明:
以下举一个样例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
package IO; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * 序列化和反序列化的操作 * */ public class serDemo{ public static void main(String[] args)
throws Exception{ ser(); // 序列化 dser(); // 反序列话 } public static void ser()
throws Exception{ File file = new File( "d:" + File.separator +
"hello.txt" ); ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream( file)); out.writeObject( new Person1( "rollen" ,
20 )); out.close(); } public static void dser()
throws Exception{ File file = new File( "d:" + File.separator +
"hello.txt" ); ObjectInputStream input = new ObjectInputStream( new FileInputStream( file)); Object obj = input.readObject(); input.close(); System.out.println(obj); } } class Person1
implements Serializable{ public Person1(){ } public Person1(String name,
int age){ this .name = name; this .age = age; } @Override public String toString(){ return "姓名:" + name +
" 年龄:" + age; } // 注意这里 private transient String name; private int age; } |
【执行结果】:
姓名:null 年龄:20
最后在给一个序列化一组对象的样例吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * 序列化一组对象 * */ public class SerDemo1{ public static void main(String[] args)
throws Exception{ Student[] stu = { new Student( "hello" ,
20 ), new Student( "world" ,
30 ), new Student( "rollen" ,
40 ) }; ser(stu); Object[] obj = dser(); for ( int i =
0 ; i < obj.length; ++i){ Student s = (Student) obj[i]; System.out.println(s); } } // 序列化 public static void ser(Object[] obj)
throws Exception{ File file = new File( "d:" + File.separator +
"hello.txt" ); ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream( file)); out.writeObject(obj); out.close(); } // 反序列化 public static Object[] dser()
throws Exception{ File file = new File( "d:" + File.separator +
"hello.txt" ); ObjectInputStream input = new ObjectInputStream( new FileInputStream( file)); Object[] obj = (Object[]) input.readObject(); input.close(); return obj; } } class Student
implements Serializable{ public Student(){ } public Student(String name,
int age){ this .name = name; this .age = age; } @Override public String toString(){ return "姓名: " + name +
" 年龄:" + age; } private String name; private int age; } |
【执行结果】:
姓名: hello 年龄:20
姓名: world 年龄:30
姓名: rollen 年龄:40