- 浏览: 203244 次
- 性别:
- 来自: 湖南
文章分类
最新评论
IO/输入输出
File类
它是IO包中唯一代表磁盘文件本身信息的类,而不是文件中内容。
它定义了一些与平台无关的方法来操纵文件,例如:创建,删除文件各重合文件。
java中的目录被当作一种特殊的文件使用,list方法可以返回目录中的所有子目录和文件名。
在Unix下的路征分隔符为(/),在Dos下的路征分隔符为(\),java可以正确处理Unix和Dos的路征分隔符。
RandomAccessFile类
它提供众多文件访问方法,支持“随机访问”方式
随机读写等长记录格式的文件时有很大的优势,仅限于操作文件,不能访问其它的IO设备,如网络,内存映像等。
String mode (r:读 w:写)//模式
两种构造方法:
new RandomAccessFile(f,"rw"); //读写方式
new RandomAccessFile(f,"r"); //只读方式
实例:(读写员工实例对象)
节点流
流是字节序列的抽象概念
文件是数据的静态存储形式,而流是指数据传输时的形态
流类分为两个大类:节点流类和过滤流类(也叫处理流类)
InputStream类
程序可以从中连续读取字节的对象叫输入流,在java中,用InputStream类来描述所有输入法流的抽象概念
int read() //从输入流中读取数据的下一个字节
int read(byte[] b) //从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
int read(byte[] b, int off, int len) //将输入流中最多 len 个数据字节读入 byte 数组
skip(long n) //跳过和丢弃此输入流中数据的 n 个字节 (包装类)
available() //返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数
mark(int readlimit) //在此输入流中标记当前的位置
markSupported() //测试此输入流是否支持 mark 和 reset 方法
reset() //将此流重新定位到最后一次对此输入流调用 mark 方法时的位置
close() //关闭此输入流并释放与该流关联的所有系统资源
OutputStream类
程序可以向其中其中写入字节的对象叫输出流,在java中,用OutPutStream类来描述所有输出流的抽象概念
write(byte[] b) //将 b.length 个字节从指定的 byte 数组写入此输出流
write(int b) //将指定的字节写入此输出流
write(byte[] b, int off, int len) //将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流
flush() //刷新此输出流并强制写出所有缓冲的输出字节
close() //关闭此输出流并释放与此流有关的所有系统资源
FileInputStream与FileOutputStream
FileInputStream和FileOutputStream类分别用来创建磁盘文件的输入和输出流对象,通过它们的构造函数来指定文件路征和文件名
创建FileInputStream实例对象时,指定的文件应当是存在和可读的。创建FileOutStream实例对象时,如果指定文件已经存在,这个文件的原内容将被覆盖清除。
对同一个磁盘文件创建FileInputStream对象的两种方式:
(1)FileInputStream inOne = new FileInputStream("hello.txt");
(2)File f = new File("hello.txt");
FileInputStream inTwo = new FileInputStream(f);
创建FileOutputStrem实例对象时,可以指定还不存在的文件名,不能指定一个已被其它程序打开了的文件。
实例:
Reader与Writer(字符)
Reader和Writer 是所有字符流的抽象基类,用于简化对字符串的输入输出编程,即用于读写文本数据
FileWriter用于写入字符流 FileOutputStream 要写入原始字节流
实例:
PipedInputStream与PipedOutStram类
PipedInputStream和PipedOutputStream 以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端,输入流是管道的接收端。
实例:
PipedWriter和PipedReader类。(字符管道通信)
使用管道流类,可以实现各个程序模块之间的松耦合通信。
ByteArrayInputStream与ByteArrayOutputStream类
ByteArrayInputStream和ByteArrayOutputStream此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据
用于以IO流的方式来完成对字节数组内容的读写,来支持类似内存虚拟文件或者内存映像文件的功能。
ByteArrayInputStream的两个构造函数:
ByteArrayInputStream(byte[] buf)
ByteArrayInputStream(byte[] bbuf, int offset, int len);
ByteArrayOutputStream的两个构造函数:
ByteArrayOutputStream()
ByteArrayOutputStream(int len);
实例:
重视IO程序代码的复用
System.in连接键盘,是InputStream类型的实例对象 System.out 连接显示器,是PrintStream类的实例对象。
不管各种底层物理设备用什么方式实现数据的终止点,InputStream的read方法总是返回-1来表示输入流的结束。
在Windows下,按下Ctrl+Z组合可以产生键盘输入流的结束标记,在liunx下,则是按下Ctrl+D组合键来产生键盘输入流的结束标记。
建议:要编程从键盘上连续读取一大段数据时,应尽量将读取数据的过程放在函数中完成,使用-1来作为键盘输入的结束点。在该函数中编写的程序代码不应直接使用System.in读取数据,而是用一个InputStream类型的形式
参数对象来读取数据,然后将System.in作为实参传递给InputStream类型的形式参数来调用该函数。
字符编码
计算机里只有数字,计算机软件里的一切都是用数字来表示的,屏幕上显示的一个个数字也不例外。
字符a对应数字是97,这种字符与数字对应的编码规则被称为ASCII(美国标准信息交换码)。ASCII的最高位是0,也就是说这些数字都在0到127之间。
中国大陆将每一个中文字符都用两个字节的数字表示,中文字符的每个字节的最高位bit都为1,中国大陆为每个中文字符制定的编码规则称为GB2312(国标码)。
在GB2312的基础上,对更多的中文字符(包括繁体)进行了编码,新的编码规则称为GBK。
在中国大陆使用的计算系统上,GBK和GB2312就被称为该系统的本地字符集。
台湾地区对中文字符集的编码规则称为BIG5(大五码)。
Unicode编码
ISO(国际标准化组织)将全世界所有的符号进行了统一编码,称之为Unicode编码。
Unicode编码的字符都占用两个字节的大小,对于ASCII码所表示的字符,只是简单地在ASCII码原来占用的一个字节前面,增加一个所有bits为0的字节。
Unicode只占用两个字节,在全世界范围内所表示的字符个数不会超过2的16次方(655536),实际上,Unicode编码中还保留了两千多个数值没有用于字符编码。
java中的字符使用的Unicode编码,java在通过Unicode保证跨平台特性的前提下,也支持本地平台字符集。
UTF-8编码
ASCII码符保持原样,仍然只占用一个字节,对于其它国家的字符,UTF-8使用两个或三个字节来表示。使用UTF-8编码的文件,通常都要用EE BB BF作为文件开头的三个字节数据。
UTF-8优点
不出现内容为0x00字节
便于应用程序检测数据在传输过程中是否发生了错误
直接处理使用ASCII码的英文文档
UTF-8的缺点
在某些特殊的文字需要三个字节(如中日韩)
UTF-16编码
UTF-16编码在Unicode基础上进行了一些细节上的扩充,增加了对Unicode编码没有包括的那些字符的表达式。
UTF-16对Unicode的扩充并没有影响Unicode编码所包括的哪些字符,只是增加了对Unicode编码没有包括的那些字符的表达方式,一个使用Unicode编码的字符就是UTF-16格式的。
Unicode编码将0XD800-0XDFFF区间的数值保留出来,UTF-16扩充的字符,占用4个字节,前面两个字节的数值为0XD8000-0XD8FF之间,后面两个字节的数值为0XDC00-0XDFFF之间。
为什么不让前面后面的两个字节的数值都位于0XD800-0XDFFF之间呢?
0XDC00-0XDFFF已经足够满足全世界各国文字;前后数值都位于0XD800-0XDFFF不便于区分两个字节。
在不同体系结构的计算机系统中,UTF-16编码的Unicode字符在内存中的字节存储顺序是不同的。
对于0X1234这样一个双字节数据,使用Little-Endian和Big-Endian两个方式在内存中存储的格式如下图所示:
如果文件以0XFE 0XFF这两个字节开头,则表明文本的其余部分是Big-Endian的UTF-16编码;如果
文件以0XFF 0XFE这两个字节开头,则表明文本的其余部分是Little-Endian的UTF-16编码。
实例:
包装类的概念与作用
通过完成某个特殊功能的类,称为包装类或者称为过滤流类
BufferedInputStream与BufferedOutputStream类
缓冲流为I/O流增加了内存缓冲区,增加缓冲区有两个基本的:
1、允许java程序一次不只操作一个字节,这样提高了程序的性能。
2、由于有了缓冲区,使得在流上执行skip、mark和reset方法都成为可能。
BufferedInputStream和BufferedOutputStream是java提供的两个缓冲区包装类,不管底层系统是否使用了缓冲区,这两个类在自己的实例对象中创建缓冲区。
BufferedInputStreamr的两个构造函数:
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in,int size)
BufferedOutputStream的两个构造函数:
BufferedOutputStream(OutputStream out)
BufferedOutputStream(OutputStream out,int size)
BufferedReader的readLine方法可以一次读取一行文本,BufferedWriter的newLine方法可以向字符流中写人不同操作系统下的换行符。
DataInputStream与DataOutStream类
DataOutputStream类提供了三个写入字符的方法:
public final void writeBytes(String s)
public final void writeChars(String s)
public final void writeUTF(String s)
DataInputStream类中有一个readUTF方法,并没有“readBytes”和“readChars”方法。 (原因读取编码不明)
编程实例:分别使用DataOutputStream类的writeUTF、writeBytes和
writeChars方法,比较这几个方法的差异。程序中所使用的流栈如下:
关闭流栈中的最上层的流对象,将会自动关闭流栈中的所有底层流对象。
PrintStream类
PrintStream类提供了一系列的print和println方法,可以将基本数据类型的数据格式化成字符串输出。
格式化输出:例如,97被格式化输出的实际字节数据为0X39和0X37。
PrintStream的3个构造函数:
PrintStream(OutputStrean out)
PrintStream(OutputStream out,boolean outoflush)
PrintStream(OutputStream out,noolean outoflush,String encoding)
与PrintStream对应的PrintWriter类,即使遇到了文本换行符(\n),PrintWriter类也不会自动清空缓冲区。
PrintWrite的println方法能根据操作系统的不同而生成相应的文本换行标识符。在Windows下的文本换行标识符是“\r\n”,而Linux下的文本换行标识符是"\n";
ObjectInputStream与ObjectOutputStream类
ObjectInputStream和ObjectOutputStream这两个包装类,用于从底层输入流中读取对象类型的数据和将对象类型的数据写入到底层输出流。
ObjectInputStream与ObjectOutputStream类所读写的对象必须实现了Serializable接口。对象中的transient(临时变量)和static类型的成员变量不会被读取和写入。
一个可以被序列化的MyClass类的定义:
字节流与字符流的转换
BufferedReader in = new BufferedReader(new InputStreamReader(System.in))读取键盘上输入的一行字符。
InputStreamReader和OutputStreamWriter,是用于将字节流转换成字符流来读写的两个类,InputStreamReader可以将一个字节流中的字节解码成字符后读取,OutputStreamWriter将字符编码成字节后写入到一个字节流中。
InputStreanReader的两个主要的构造函数:
InputStreamRead(InputStream in)
InputStreamRead(InputStream in,String CharsetName);
OutputStreanWriter的两个主要的构造函数:
OutputStreamWriter(OutputStream out)
OutputStreamWriter(OutputStream out,String CharsetName);
避免频繁地在字符与字节间进行转换,最好不要直接使用InputStreamRead和OutputStreamWriter类来读写数据,应尽量使用BufferedWrite类包装OutputStreamWriter类,用于BufferderReader类包装InputStreamrader.
java程序与其它进程的数据通信
在java程序可以用Process类的实例对象来表示子进程,子进程的标准输入和输出不再连接到键盘和显示器,而是以管道流的形式连接到父进程的一个输出流和输入流对象上。
调用Process类的getOutputStream和getInputStream方法可以获得连接到子进程的输出流和输入流对象。
编程实例:在TestInOut类中启动java.exe命令执行另外一个MyTest类,TestInOut和MyTest通过进程间的管道相互传递数据。
管道缓冲区满后,与PipedInputStram相连的pipedOutputStream无法再写入新的数据,PiedOutputStream.write方法处于阻塞状态。
记住调用Process类的destroy方法结束子进程的运行。
字节输出流类
字符输入流类
字符输出流类
Decorator设计模式
在程序中用一个对象(the Decorators)1包装另外的一个对象,这是一种被称为Decorator的设计模式。
如果要设计自己的IO包装类,这个类需要继承以FilterXXX命名的类,设计一个对输入输出包装类:
RecordInputStream和RecordOutputStram,来完成从数据库文件中读取记录和往数据库文件中写入记录。
Exception类从Throwable类继承的三个PrintStackTrace方法的定义如下:
public void printStackTrace();
public void printStackTrace(PrintStream s)
public void printStackTrace(PrintWriter s)
实例:(将异常信息储存到字符串中)
File类
它是IO包中唯一代表磁盘文件本身信息的类,而不是文件中内容。
它定义了一些与平台无关的方法来操纵文件,例如:创建,删除文件各重合文件。
java中的目录被当作一种特殊的文件使用,list方法可以返回目录中的所有子目录和文件名。
在Unix下的路征分隔符为(/),在Dos下的路征分隔符为(\),java可以正确处理Unix和Dos的路征分隔符。
package cn.com.io; import java.io.File; import java.io.IOException; import java.util.Date; public class FileTest { public static void main(String[] args) { File f = new File("1.txt"); if(f.exists()){ //文件是否存在 f.delete(); ////删除文件 }else{ try { f.createNewFile(); } catch (IOException e) { e.printStackTrace(); //创建文件 } } System.out.println("获取文件名:"+f.getName()); System.out.println("获取文件的路径:"+f.getPath()); System.out.println("获取文件的绝对路征:"+f.getAbsolutePath()); System.out.println("获取文件的父目录:"+f.getParent()); System.out.println(f.exists() ? "exists" : "not exists"); System.out.println("判断文件是否可读:"+(f.canRead() ? "read" : "not read")); System.out.println("判断文件是否可写"+(f.canWrite() ? "write" : "not write")); System.out.println("判断文件是否是目录:"+(f.isDirectory() ? "directory" : "not directory")); System.out.println("获取文件的最后一次被修改的时间:"+new Date(f.lastModified()).toString()); } }
RandomAccessFile类
它提供众多文件访问方法,支持“随机访问”方式
随机读写等长记录格式的文件时有很大的优势,仅限于操作文件,不能访问其它的IO设备,如网络,内存映像等。
String mode (r:读 w:写)//模式
两种构造方法:
new RandomAccessFile(f,"rw"); //读写方式
new RandomAccessFile(f,"r"); //只读方式
实例:(读写员工实例对象)
package cn.com.io; public class Employee { public String name = null; public int age = 0; public static final int LEN = 8; public Employee(String name, int age){ if(name.length() > LEN){ name = name.substring(0,LEN); }else{ while (name.length() < LEN) { name += "\u0000"; } } this.name = name; this.age = age; } }
package cn.com.io; import java.io.RandomAccessFile; public class RandomAccessFileTest { public static void main(String[] args) { Employee e1 = new Employee("张三", 20); Employee e2 = new Employee("李四", 21); Employee e3 = new Employee("王五", 22); try { RandomAccessFile ra = new RandomAccessFile("employee.txt", "rw"); ra.writeChars(e1.name); ra.writeInt(e1.age); ra.writeChars(e2.name); ra.writeInt(e2.age); ra.writeChars(e3.name); ra.writeInt(e3.age); ra.close(); String strName = ""; RandomAccessFile raf = new RandomAccessFile("employee.txt", "r"); raf.skipBytes(Employee.LEN * 2 + 4); for(int i=0;i<Employee.LEN;i++){ strName += raf.readChar(); } System.out.println(strName.trim() + ":" + raf.readInt()); raf.seek(0); strName = ""; for(int i=0;i<Employee.LEN;i++){ strName += raf.readChar(); } System.out.println(strName.trim() + ":" + raf.readInt()); raf.skipBytes(Employee.LEN * 2 + 4); strName = ""; for(int i=0;i<Employee.LEN;i++){ strName += raf.readChar(); } System.out.println(strName.trim() + ":" + raf.readInt()); raf.close(); } catch (Exception e) { e.printStackTrace(); } } }
节点流
流是字节序列的抽象概念
文件是数据的静态存储形式,而流是指数据传输时的形态
流类分为两个大类:节点流类和过滤流类(也叫处理流类)
InputStream类
程序可以从中连续读取字节的对象叫输入流,在java中,用InputStream类来描述所有输入法流的抽象概念
int read() //从输入流中读取数据的下一个字节
int read(byte[] b) //从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
int read(byte[] b, int off, int len) //将输入流中最多 len 个数据字节读入 byte 数组
skip(long n) //跳过和丢弃此输入流中数据的 n 个字节 (包装类)
available() //返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数
mark(int readlimit) //在此输入流中标记当前的位置
markSupported() //测试此输入流是否支持 mark 和 reset 方法
reset() //将此流重新定位到最后一次对此输入流调用 mark 方法时的位置
close() //关闭此输入流并释放与该流关联的所有系统资源
OutputStream类
程序可以向其中其中写入字节的对象叫输出流,在java中,用OutPutStream类来描述所有输出流的抽象概念
write(byte[] b) //将 b.length 个字节从指定的 byte 数组写入此输出流
write(int b) //将指定的字节写入此输出流
write(byte[] b, int off, int len) //将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流
flush() //刷新此输出流并强制写出所有缓冲的输出字节
close() //关闭此输出流并释放与此流有关的所有系统资源
FileInputStream与FileOutputStream
FileInputStream和FileOutputStream类分别用来创建磁盘文件的输入和输出流对象,通过它们的构造函数来指定文件路征和文件名
创建FileInputStream实例对象时,指定的文件应当是存在和可读的。创建FileOutStream实例对象时,如果指定文件已经存在,这个文件的原内容将被覆盖清除。
对同一个磁盘文件创建FileInputStream对象的两种方式:
(1)FileInputStream inOne = new FileInputStream("hello.txt");
(2)File f = new File("hello.txt");
FileInputStream inTwo = new FileInputStream(f);
创建FileOutputStrem实例对象时,可以指定还不存在的文件名,不能指定一个已被其它程序打开了的文件。
实例:
package cn.com.io; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; public class FileStream { public static void main(String[] args) { try { FileOutputStream out = new FileOutputStream("hello.txt"); out.write("hello world".getBytes()); out.close(); byte[] buf = new byte[1024]; File f = new File("hello.txt"); FileInputStream in = new FileInputStream(f); int len = in.read(buf); in.close(); System.out.println(new String(buf,0,len)); } catch (Exception e) { e.printStackTrace(); } } }
Reader与Writer(字符)
Reader和Writer 是所有字符流的抽象基类,用于简化对字符串的输入输出编程,即用于读写文本数据
FileWriter用于写入字符流 FileOutputStream 要写入原始字节流
实例:
package cn.com.io; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class FileStream2 { public static void main(String[] args) { try { FileWriter out = new FileWriter("hello.txt"); out.write("hello world2"); out.flush(); out.close(); char[] buf = new char[1024]; FileReader in = new FileReader("hello.txt"); int len = in.read(buf); System.out.println(new String(buf,0,len)); in.close(); } catch (IOException e) { e.printStackTrace(); } } }
PipedInputStream与PipedOutStram类
PipedInputStream和PipedOutputStream 以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端,输入流是管道的接收端。
实例:
package cn.com.io; import java.io.IOException; import java.io.PipedOutputStream; public class PipedSend extends Thread { private PipedOutputStream out = new PipedOutputStream(); public PipedOutputStream getOutputStream(){ return out; } public void run(){ String strInfo = new String("hello receiver"); try { out.write(strInfo.getBytes()); out.close(); } catch (IOException e) { e.printStackTrace(); } } }
package cn.com.io; import java.io.IOException; import java.io.PipedInputStream; public class PipedReceiver extends Thread { private PipedInputStream in = new PipedInputStream(); public PipedInputStream getInputStream(){ return in; } public void run(){ byte[] buf = new byte[1024]; try { int len = in.read(buf); in.close(); System.out.println("the following message comes from sender:\n" + new String(buf,0,len)); } catch (IOException e) { e.printStackTrace(); } } }
package cn.com.io; import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; public class PipedStreamTest { public static void main(String[] args) { PipedSend s = new PipedSend(); PipedReceiver r = new PipedReceiver(); PipedOutputStream out = s.getOutputStream(); PipedInputStream in = r.getInputStream(); s.start(); r.start(); try { out.connect(in); } catch (IOException e) { e.printStackTrace(); } } }
PipedWriter和PipedReader类。(字符管道通信)
使用管道流类,可以实现各个程序模块之间的松耦合通信。
ByteArrayInputStream与ByteArrayOutputStream类
ByteArrayInputStream和ByteArrayOutputStream此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据
用于以IO流的方式来完成对字节数组内容的读写,来支持类似内存虚拟文件或者内存映像文件的功能。
ByteArrayInputStream的两个构造函数:
ByteArrayInputStream(byte[] buf)
ByteArrayInputStream(byte[] bbuf, int offset, int len);
ByteArrayOutputStream的两个构造函数:
ByteArrayOutputStream()
ByteArrayOutputStream(int len);
实例:
package cn.com.io; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class ByteArrayTest { public static void main(String[] args) { String tmp = "abcdefghigklmnopqrstuvwxyz"; byte[] src = tmp.getBytes(); ByteArrayInputStream in = new ByteArrayInputStream(src); ByteArrayOutputStream out = new ByteArrayOutputStream(); transform(in, out); byte[] result = out.toByteArray(); System.out.println(new String(result)); transform(System.in, System.out); } public static void transform(InputStream in, OutputStream out){ try { int ch = 0; while((ch = in.read()) != -1){ int upperCh = Character.toUpperCase((char)ch); out.write(upperCh); } } catch (IOException e) { e.printStackTrace(); } } }
重视IO程序代码的复用
System.in连接键盘,是InputStream类型的实例对象 System.out 连接显示器,是PrintStream类的实例对象。
不管各种底层物理设备用什么方式实现数据的终止点,InputStream的read方法总是返回-1来表示输入流的结束。
在Windows下,按下Ctrl+Z组合可以产生键盘输入流的结束标记,在liunx下,则是按下Ctrl+D组合键来产生键盘输入流的结束标记。
建议:要编程从键盘上连续读取一大段数据时,应尽量将读取数据的过程放在函数中完成,使用-1来作为键盘输入的结束点。在该函数中编写的程序代码不应直接使用System.in读取数据,而是用一个InputStream类型的形式
参数对象来读取数据,然后将System.in作为实参传递给InputStream类型的形式参数来调用该函数。
字符编码
计算机里只有数字,计算机软件里的一切都是用数字来表示的,屏幕上显示的一个个数字也不例外。
字符a对应数字是97,这种字符与数字对应的编码规则被称为ASCII(美国标准信息交换码)。ASCII的最高位是0,也就是说这些数字都在0到127之间。
中国大陆将每一个中文字符都用两个字节的数字表示,中文字符的每个字节的最高位bit都为1,中国大陆为每个中文字符制定的编码规则称为GB2312(国标码)。
在GB2312的基础上,对更多的中文字符(包括繁体)进行了编码,新的编码规则称为GBK。
在中国大陆使用的计算系统上,GBK和GB2312就被称为该系统的本地字符集。
台湾地区对中文字符集的编码规则称为BIG5(大五码)。
Unicode编码
ISO(国际标准化组织)将全世界所有的符号进行了统一编码,称之为Unicode编码。
Unicode编码的字符都占用两个字节的大小,对于ASCII码所表示的字符,只是简单地在ASCII码原来占用的一个字节前面,增加一个所有bits为0的字节。
Unicode只占用两个字节,在全世界范围内所表示的字符个数不会超过2的16次方(655536),实际上,Unicode编码中还保留了两千多个数值没有用于字符编码。
java中的字符使用的Unicode编码,java在通过Unicode保证跨平台特性的前提下,也支持本地平台字符集。
UTF-8编码
ASCII码符保持原样,仍然只占用一个字节,对于其它国家的字符,UTF-8使用两个或三个字节来表示。使用UTF-8编码的文件,通常都要用EE BB BF作为文件开头的三个字节数据。
UTF-8优点
不出现内容为0x00字节
便于应用程序检测数据在传输过程中是否发生了错误
直接处理使用ASCII码的英文文档
UTF-8的缺点
在某些特殊的文字需要三个字节(如中日韩)
UTF-16编码
UTF-16编码在Unicode基础上进行了一些细节上的扩充,增加了对Unicode编码没有包括的那些字符的表达式。
UTF-16对Unicode的扩充并没有影响Unicode编码所包括的哪些字符,只是增加了对Unicode编码没有包括的那些字符的表达方式,一个使用Unicode编码的字符就是UTF-16格式的。
Unicode编码将0XD800-0XDFFF区间的数值保留出来,UTF-16扩充的字符,占用4个字节,前面两个字节的数值为0XD8000-0XD8FF之间,后面两个字节的数值为0XDC00-0XDFFF之间。
为什么不让前面后面的两个字节的数值都位于0XD800-0XDFFF之间呢?
0XDC00-0XDFFF已经足够满足全世界各国文字;前后数值都位于0XD800-0XDFFF不便于区分两个字节。
在不同体系结构的计算机系统中,UTF-16编码的Unicode字符在内存中的字节存储顺序是不同的。
对于0X1234这样一个双字节数据,使用Little-Endian和Big-Endian两个方式在内存中存储的格式如下图所示:
如果文件以0XFE 0XFF这两个字节开头,则表明文本的其余部分是Big-Endian的UTF-16编码;如果
文件以0XFF 0XFE这两个字节开头,则表明文本的其余部分是Little-Endian的UTF-16编码。
实例:
package cn.com.io; import java.io.UnsupportedEncodingException; public class Charcode { public static void main(String[] args) { System.setProperty("sun.jnu.encoding", "iso8859-1"); //设置属性文件 System.getProperties().list(System.out); //获得属性文件 String strChina = "中国"; for(int i=0;i<strChina.length();i++){//toHexString(int i) 以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式 System.out.println(Integer.toHexString((int)strChina.charAt(i))); } try { byte[] buf = strChina.getBytes("gb2312"); for(int str : buf){ System.out.println(Integer.toHexString(str)); } for(int i=0;i<buf.length;i++){ System.out.write(buf[i]); //输出流形式输出 } System.out.println(); //刷新缓冲区 System.out.write(buf,0,4); //自动刷新缓冲区 System.out.println("\n中国"); //PrintStream.println(String str) } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } }
package cn.com.io; import java.io.IOException; public class CharDecode { public static void main(String[] args) { System.getProperties().put("file encoding", "iso8859-1"); System.out.println("please enter a chinese String:"); byte[] buf = new byte[1024]; int pos = 0; String strInfo; int ch; while(true){ try { ch = System.in.read(); System.out.println(Integer.toHexString(ch)); switch(ch){ case '\r': break; case '\n': strInfo = new String(buf,0,pos,"gb2312"); for(int i=0;i<strInfo.length();i++){ System.out.println(Integer.toHexString(strInfo.charAt(i))); } System.out.println(new String(strInfo.getBytes("iso8859-1"),"gb2312")); pos = 0; break; default: buf[pos++] = (byte) ch; } } catch (IOException e) { e.printStackTrace(); } } } }
包装类的概念与作用
通过完成某个特殊功能的类,称为包装类或者称为过滤流类
BufferedInputStream与BufferedOutputStream类
缓冲流为I/O流增加了内存缓冲区,增加缓冲区有两个基本的:
1、允许java程序一次不只操作一个字节,这样提高了程序的性能。
2、由于有了缓冲区,使得在流上执行skip、mark和reset方法都成为可能。
BufferedInputStream和BufferedOutputStream是java提供的两个缓冲区包装类,不管底层系统是否使用了缓冲区,这两个类在自己的实例对象中创建缓冲区。
BufferedInputStreamr的两个构造函数:
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in,int size)
BufferedOutputStream的两个构造函数:
BufferedOutputStream(OutputStream out)
BufferedOutputStream(OutputStream out,int size)
BufferedReader的readLine方法可以一次读取一行文本,BufferedWriter的newLine方法可以向字符流中写人不同操作系统下的换行符。
DataInputStream与DataOutStream类
DataOutputStream类提供了三个写入字符的方法:
public final void writeBytes(String s)
public final void writeChars(String s)
public final void writeUTF(String s)
DataInputStream类中有一个readUTF方法,并没有“readBytes”和“readChars”方法。 (原因读取编码不明)
编程实例:分别使用DataOutputStream类的writeUTF、writeBytes和
writeChars方法,比较这几个方法的差异。程序中所使用的流栈如下:
关闭流栈中的最上层的流对象,将会自动关闭流栈中的所有底层流对象。
package cn.com.io; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; public class DataStreamTest { public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream("count.txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); DataOutputStream dos = new DataOutputStream(bos); dos.writeUTF("China 中国"); dos.writeBytes("China 中国"); dos.writeChars("China 中国"); dos.close(); FileInputStream fis = new FileInputStream("count.txt"); BufferedInputStream bis = new BufferedInputStream(fis); DataInputStream dis = new DataInputStream(bis); System.out.println(dis.readUTF()); byte[] buf = new byte[1024]; int len = dis.read(buf); System.out.println(new String(buf,0,len)); dis.close(); } }
PrintStream类
PrintStream类提供了一系列的print和println方法,可以将基本数据类型的数据格式化成字符串输出。
格式化输出:例如,97被格式化输出的实际字节数据为0X39和0X37。
PrintStream的3个构造函数:
PrintStream(OutputStrean out)
PrintStream(OutputStream out,boolean outoflush)
PrintStream(OutputStream out,noolean outoflush,String encoding)
与PrintStream对应的PrintWriter类,即使遇到了文本换行符(\n),PrintWriter类也不会自动清空缓冲区。
PrintWrite的println方法能根据操作系统的不同而生成相应的文本换行标识符。在Windows下的文本换行标识符是“\r\n”,而Linux下的文本换行标识符是"\n";
ObjectInputStream与ObjectOutputStream类
ObjectInputStream和ObjectOutputStream这两个包装类,用于从底层输入流中读取对象类型的数据和将对象类型的数据写入到底层输出流。
ObjectInputStream与ObjectOutputStream类所读写的对象必须实现了Serializable接口。对象中的transient(临时变量)和static类型的成员变量不会被读取和写入。
一个可以被序列化的MyClass类的定义:
public class MyClass implements Serializable{ public transient Thread t; private String CustomerID; private int total; }实例:
package cn.com.io; import java.io.Serializable; public class Student implements Serializable { private static final long serialVersionUID = 1L; int id; String name; int age; String department; public Student(int id,String name,int age,String department){ this.id = id; this.name = name; this.age = age; this.department = department; } }
package cn.com.io; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class Serialization { public static void main(String[] args) throws Exception { Student stu1 = new Student(19, "张三", 20, "数学系"); Student stu2 = new Student(20, "李四", 22, "计算机系"); FileOutputStream fos = new FileOutputStream("student.txt"); ObjectOutputStream os = new ObjectOutputStream(fos); os.writeObject(stu1); os.writeObject(stu2); os.close(); FileInputStream fis = new FileInputStream("student.txt"); ObjectInputStream is = new ObjectInputStream(fis); stu1 = (Student) is.readObject(); stu2 = (Student) is.readObject(); is.close(); System.out.println("id:"+stu1.id+" name:"+stu1.name+" age:"+stu1.age+" department:"+stu1.department); System.out.println("id:"+stu2.id+" name:"+stu2.name+" age:"+stu2.age+" department:"+stu2.department); } }
字节流与字符流的转换
BufferedReader in = new BufferedReader(new InputStreamReader(System.in))读取键盘上输入的一行字符。
InputStreamReader和OutputStreamWriter,是用于将字节流转换成字符流来读写的两个类,InputStreamReader可以将一个字节流中的字节解码成字符后读取,OutputStreamWriter将字符编码成字节后写入到一个字节流中。
InputStreanReader的两个主要的构造函数:
InputStreamRead(InputStream in)
InputStreamRead(InputStream in,String CharsetName);
OutputStreanWriter的两个主要的构造函数:
OutputStreamWriter(OutputStream out)
OutputStreamWriter(OutputStream out,String CharsetName);
避免频繁地在字符与字节间进行转换,最好不要直接使用InputStreamRead和OutputStreamWriter类来读写数据,应尽量使用BufferedWrite类包装OutputStreamWriter类,用于BufferderReader类包装InputStreamrader.
java程序与其它进程的数据通信
在java程序可以用Process类的实例对象来表示子进程,子进程的标准输入和输出不再连接到键盘和显示器,而是以管道流的形式连接到父进程的一个输出流和输入流对象上。
调用Process类的getOutputStream和getInputStream方法可以获得连接到子进程的输出流和输入流对象。
编程实例:在TestInOut类中启动java.exe命令执行另外一个MyTest类,TestInOut和MyTest通过进程间的管道相互传递数据。
管道缓冲区满后,与PipedInputStram相连的pipedOutputStream无法再写入新的数据,PiedOutputStream.write方法处于阻塞状态。
记住调用Process类的destroy方法结束子进程的运行。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class MyTest { public static void main(String[] args) throws IOException { BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in)); while(true){ String strLine = bfr.readLine(); if(strLine != null){ System.out.println("hi:" +strLine); }else{ return; } } } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; public class TestInOut implements Runnable{ Process p = null; public TestInOut() { try { p =Runtime.getRuntime().exec("java MyTest");//外部命令 new Thread(this).start(); //this当前对象 } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { TestInOut tio = new TestInOut(); tio.send(); } public void send(){ OutputStream ops = p.getOutputStream(); try { while(true){ ops.write("help\r\n".getBytes()); } } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { InputStream in = p.getInputStream(); BufferedReader bfr = new BufferedReader(new InputStreamReader(in)); String strLine; try { while(true){ strLine = bfr.readLine(); if(strLine != null){ System.out.println(strLine); }else{ return; } } } catch (IOException e) { e.printStackTrace(); } } }字节输入流类
字节输出流类
字符输入流类
字符输出流类
Decorator设计模式
在程序中用一个对象(the Decorators)1包装另外的一个对象,这是一种被称为Decorator的设计模式。
如果要设计自己的IO包装类,这个类需要继承以FilterXXX命名的类,设计一个对输入输出包装类:
RecordInputStream和RecordOutputStram,来完成从数据库文件中读取记录和往数据库文件中写入记录。
Exception类从Throwable类继承的三个PrintStackTrace方法的定义如下:
public void printStackTrace();
public void printStackTrace(PrintStream s)
public void printStackTrace(PrintWriter s)
实例:(将异常信息储存到字符串中)
package cn.com.io; import java.io.PrintWriter; import java.io.StringWriter; public class TestPrintWriter { public static void main(String[] args) { try{ throw new Exception("test"); }catch(Exception e){ StringWriter sw = new StringWriter(); PrintWriter pw =new PrintWriter(sw); e.printStackTrace(pw); System.out.println(e.getMessage()); System.out.println(sw.toString()); } } }
- java.zip (28.3 KB)
- 下载次数: 6
发表评论
-
java版 纸牌
2012-05-30 15:43 855java 纸牌游戏,有连翻一张或三张两种玩法,程序在部分点击区 ... -
java版 推箱子
2012-01-12 17:24 1488java版 推箱子源码 import javax.swin ... -
java 基础加强
2011-01-07 14:17 756java基础 jdk1.5 新特征 ... -
网络五子棋
2011-01-05 15:50 1040最近空限,完成之前未完成的网络五子棋,它是面向TCP协 ... -
java图片处理:文字图像水印 缩放补白
2010-12-28 11:40 1159package com.util; import j ... -
Java2D绘制五星红旗
2010-12-27 09:17 1151/** 使用Java2D绘制五星红旗 五星 ... -
网络编程
2010-12-21 14:16 1228网络编程 网络编程的基础知识 网络协议与TCP/IP 计算 ... -
银行业务调度系统
2010-08-19 18:34 1325模拟实现银行业务调度系统逻辑,具体需求如下: 银行内有6 ... -
交通灯管理系统
2010-08-18 13:16 1290模拟实现十字路口的交通灯管理系统逻辑,具体需求如下: 异 ... -
贪吃蛇游戏
2010-08-17 08:32 1696对大多数人来说,要想自己编写出《贪吃蛇》游戏的程序 ... -
蜘蛛牌
2010-08-15 00:17 1860蜘蛛牌在朴克牌游戏当中是比较有趣的游戏,特别是闯关成功 ... -
j2se版俄罗斯方块
2009-10-21 21:22 14541.图形界面 import java.awt.*; ... -
豆子吃妖精
2009-10-19 21:30 766本程序是运用了图形化画版和多程技术,只支持固定运行轨迹, ... -
连连看
2009-10-09 20:54 1012java不易开发大型游戏,但任一语言都有是相通,本程序运 ... -
Globle Get 多线程下载系统
2009-10-07 21:41 1085GlobalGet”是实现HTTP协议和FTP协议的多线程下载 ... -
控制台五子棋
2009-08-17 20:15 914<p>这是一个控制台的五子棋,它的妙处是它算法侦听 ...
相关推荐
Java IO(Input/Output)是Java编程语言中用于处理输入和输出操作的重要组成部分。它提供了丰富的类库,允许程序员在程序中实现数据的读写,无论是从硬盘、网络、内存,还是其他I/O设备。Java IO的核心在于其流的...
OTIS 300VF电梯IO输入输出简易表 OTIS 300VF电梯IO输入输出简易表是Otis Elevator Company开发的一款电梯控制系统,主要用于电梯的IO输入输出管理。本文档提供了该系统的详细配置信息,包括Ring Car Board II With ...
IO口输入输出配置是其基础且至关重要的功能,用于实现设备间的通信和控制。本文将深入探讨STM32 F103的IO口配置,包括输出高低电平控制和读取输入状态。 首先,我们要了解STM32的GPIO(General-Purpose Input/...
在KUKA机器人的KR C4标准控制柜中,IO输入输出模块的接线和组态是确保机器人系统与外部设备交互的关键步骤。本篇主要介绍如何进行这些操作。 首先,组态步骤需要借助WorkVisual软件。在启动WorkVisual但不打开任何...
总结来说,理解和掌握Java的I/O流可以帮助你有效地处理数据输入输出,线程管理则让你能够编写并发程序,特殊for语句简化了代码,而文件读写则是日常开发的基本技能。这些知识点的掌握程度直接影响到你在Java考试中的...
想了解IO输入输出流的学者可以看看,里面有详细的讲解及源代码。
库卡KUKA机器人输入输出IO信号定义表
Java IO(输入输出)是Java编程语言中处理数据输入和输出的核心部分,它提供了一系列类和接口用于在程序与外部资源之间传输数据。在Java中,IO操作涉及到文件的读写、流的处理以及网络通信等。以下是关于Java IO中的...
西门子触摸屏实现监控-PLC-所有输入输出IO程序下载 西门子触摸屏监控PLC所有输入输出IO信号状态是通过使用西门子触摸屏程序设置来实现的。该程序设置包括输入I点监控和输出Q点监控两部分。 在输入I点监控部分,...
标题中的“IO标准输入输出”指的是Java编程语言中的标准输入流(System.in)和标准输出流(System.out)。这是程序与用户交互的基本方式,用于读取键盘输入和向控制台打印输出。 在Java中,标准输入输出是通过...
KUKA机器人输入输出IO信号测试 KUKA机器人IO信号测试是非常重要的一项功能,在机器人进行I/O通讯时,需要监控I/O信号的状态,或者与外部进行输入、输出信号交互。下面是KUKA机器人IO信号测试的详细知识点: 一、在...
Java IO(输入输出)是Java编程中至关重要的一个部分,它负责处理程序与外部资源之间的数据传输。在Java中,IO被设计成一种抽象的概念,允许开发者以统一的方式处理各种类型的输入和输出设备,如硬盘、内存、网络...
Java中的IO(输入/输出)和线程是两个核心概念,它们在开发高效、响应性强的应用程序时起着至关重要的作用。输入/输出处理数据的传输,而多线程则涉及程序的并发执行。 首先,让我们深入理解Java的IO系统。Java.IO...
Java中的IO(输入/输出)是一种用于与外部资源(如文件、网络连接、数据库等)进行数据交互的机制。在Java中,主要使用java.io包提供的类和接口来进行IO操作。
西门子精智触摸屏是工业自动化领域广泛应用的人机交互界面,它提供了丰富的功能,包括对输入输出(IO)变量的监控与控制。在设计触摸屏应用时,为确保系统的安全性和稳定性,我们通常需要为输入输出变量设置上下限值...
在实际操作中,理解并能查看机器人的输入输出(IO)信号至关重要,因为这些信号控制着机器人与周围设备的交互。本篇将详细介绍如何在KUKA机器人控制系统中查看输入输出IO信号。 首先,打开KUKA机器人的控制系统界面...
适用于初学者 io输入输出的简单方法 对初学者很用用处
这时,我们需要扩展其数字量IO来增加输入输出点数,以实现更精细的控制功能。 首先,V20变频器允许用户通过连接外部IO模块来扩展其输入和输出。这些模块通常包括数字量输入模块和数字量输出模块,它们可以提供额外...