`
manwuyuantao
  • 浏览: 7836 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

Java编程语言-IO

 
阅读更多

 

 

 

1.18 IO(Input Output)

1.18.1理解IO

 

IO流用来处理设备之间的数据传输,Java用于操作流的对象都在IO包中。

IO流按数据分为:字节流和字符流。

IO流按流向分为:输入流和输出流。

IO流的常用基类:

1.字节流的抽象基类:InputStreamOutputStream

2.字符流的抽象基类:ReaderWriter

注:由这四个类派生出来的子类名称都是以其父类名作为为子类名的后缀。

如:InputStream的子类FileInputStream

Reader的子类FileReader

 

1.18.2字符流

举例:

public static void main(String[] args)throws IOException

{

//创建一个FileWriter对象,此对象初始化时就比须要明确被操作的文件。

//而且此文件会被创建到指定目录下,如果目录下有同名文件,将会被覆盖。

//其实该步就是在明确数据要存放的目的地。

FileWriter fw = new FileWriter("demo.txt");

 

//调用write方法,将字符串写入到流中。

fw.write("asfsdfdf");

 

//刷新流对象中的缓冲中的数据,将数据刷新到目的地。

fw.flush();

 

//关闭流资源,但是关闭前会刷新一次缓冲中的数据并将数据刷新到目的地。

fw.close();

}

IO异常的处理方式:

举例:

public static void main(String[] args)

{

FileWriter fw = null;

try

{

fw = new FileWriter("demo.txt");

fw.write("asfsdfdf");

}

catch (IOException e)

{

System.out.println(e.toString());

}

finally

{

try

{

if(fw!=null)

fw.close();

}

catch (IOException e)

{

System.out.println(e.toString()):

}

}

}

 

文件的续写:

public static void main(String[] args)

{

FileWriter fw = null;

try

{

//传递一个ture参数,代表不覆盖已有的文件,并在已有文件进行续写。

fw = new FileWriter("demo.txt",true);

fw.write("asfsdfdf");

}

catch (IOException e)

{

System.out.println(e.toString());

}

finally

{

try

{

if(fw!=null)

fw.close();

}

catch (IOException e)

{

System.out.println(e.toString()):

}

}

}

 

文件读取:

public static void main(String[] args) throws IOException

{

//创建一个文件读取流对象,并初始化时指定名称的文件相关联。

//要保证此文件是已存在,如不存在会发生异常:FileNotFoundException

FileReader fr = new FileReader("demo.txt");

 

//调用读取流对象的read方法。

//read方法一次只读一个字符,而且会自动向下读取。当读取完后会返回-1.

int ch = 0;

while((ch = fr.read())!=-1)

System.out.print((char)ch);

fr.close();

}

 

拷贝文本文件:

import java.io.*;

class CopyFile

{

public static void main(String[] args)

{

FileWriter fw = null;

FileReader fr = null;

try

{

fw = new FileWriter("demo_副本.txt");

fr = new FileReader("demo.txt");

char[] buf = new char[1024];

int len = 0;

while ((len=fr.read(buf))!=-1)

{

fw.write(buf,0,len);

}

}

catch (IOException e)

{

throw new RuntimeException("拷贝文件失败!");

}

finally

{

if(fr!=null)

try

{

fr.close();

}

catch (IOException e)

{

throw new RuntimeException("拷贝文件失败!");

}

if(fw!=null)

try

{

fw.close();

}

catch (IOException e)

{

throw new RuntimeException("拷贝文件失败!");

}

}

}

}

 

1.18.3字符缓冲流

缓冲区的出现提高了对数据的读写效率。

对应的类:BufferedWriterBufferedReader

缓冲区要结合流才可以使用,在流的基础上对流的功能进行了增强。

注意:缓冲类是继承了基类所以方法也继承了基类,另外BufferedWriter类中新增加了newLine()插入换行符的方法;BufferedReader类中新增了readLine()读取整行文本的方法。

 

BufferedReader类下的一个子类:LineNumberReader此类定义了方法 setLineNumber(int) getLineNumber(),它们可分别用于设置和获取当前行号。

利用缓冲区对拷贝文本文件进行优化如下:

import java.io.*;

class CopyFile

{

public static void main(String[] args)

{

BufferedWriter bufw = null;

BufferedReader bufr = null;

try

{

bufw =new BufferedWriter(new FileWriter("demo_副本.txt"));

bufr =new BufferedReader(new FileReader("demo.txt"));

String s = null;

while ((s=bufr.readLine())!=null)

{

bufw.write(s);

//bufw.newLine();

}

}

catch (IOException e)

{

throw new RuntimeException("拷贝文件失败!");

}

finally

{

if(bufr!=null)

try

{

bufr.close();

}

catch (IOException e)

{

throw new RuntimeException("拷贝文件失败!");

}

if(bufw!=null)

try

{

bufw.close();

}

catch (IOException e)

{

throw new RuntimeException("拷贝文件失败!");

}

}

}

}

 

1.18.4装饰(封装)设计模式

当想要对已有的对象进行功能增强时,可以定义类将已有的对象传入,基于已有的功能进行增强并提供出去,那么自定义的类称为装饰类。装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能提供更强的功能。

装饰与继承的区别:

装饰模式比继承灵活,避免了继承体系的臃肿,而且降低了类于类之间的关系。

装饰类因为增强的功能和已有对象具备的功能是相同的,只不过提供了更强的功能,所以装饰类和被装饰类通常都是属于一个体系。

 

1.18.5字节流

字节流的操作方法与字符流类似,只是字节流写入时没有使用到缓冲区时不需要进行刷新。

InputStream读取:字节流读取类中有一个独有方法:available(),此方法返回的是int型,也就是返回的是读取文件的字节数。

 

1.18.6字节缓冲流

BufferedOutputStream

BufferedInputStream

 

1.18.7读取转换流

InputStreamReader流是Reader下的一个子类,是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。为了达到最高效率,可要考虑在 BufferedReader内包装 InputStreamReader

例如:

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

 

1.18.8写入转换流

OutputStreamWriter是字符流通向字节流的桥梁:可使用指定的 charset将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

为了获得最高效率,可考虑将 OutputStreamWriter包装到 BufferedWriter中,以避免频繁调用转换器。

例如:

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));

 

注意:通常涉及到字符编码转换时会用到转换流,因为转换流可以指定编码表(字符集)

1.18.9流操作的基本规律

通过三步来明确来完成使用哪个流对象。

1,明确源和目的。

源:输入流:InputStream Reader

目的:输出流:OutputStream Writer

2,操作的数据是否是纯文体。

是:字符流。

不是:字节流。

3,当体系明确后,在明确要使用哪个具体的对象。

通过设备来进行区分:

源设备包括:内存,硬盘,键盘。

目的设备包括:内存,硬盘,控制台。

 

异常的日志信息:

举例:

import java.io.*;

import java.util.*;

import java.text.*;

class ExceptionInfo

{

public static void main(String[] args)

{

try

{

int[] arr = new int[2];

System.out.println(arr[3]);

}

catch (Exception e)

{

try

{

Date d =new Date();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String s = sdf.format(d);

PrintStream ps = new PrintStream("exeception.log");

ps.println(s);

System.setOut(ps);

}

catch (IOException ex)

{

throw new RuntimeException("日志文件创建失败");

}

e.printStackTrace(System.out);

}

}

}

 

//实际开发当时使用log4j工具即可,以上只为演示。

 

1.18.10 IO File

File类用来将文件或文件夹封装成对象,方便对文件与文件夹的属性信息进行操作。

File对象可以作为参数传递给流的构造函数。

File类中常用的静态字段:separator与系统有关的默认名称分隔符

File类中的一些常用方法:

1.创建

boolean createNewFile()在指定位置创建文件,如果该文件已经存在则不创建。

static File createTempFile( , ): 在指定位置创建临时文件

boolean mkdir() 创建此抽象路径名指定的目录。

boolean mkdirs() 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。

boolean renameTo(File dest) 重新命名此抽象路径名表示的文件。

2.删除

boolean delete():

void deleteOnExit():在程序退出时删除指定文件。

3.判断

boolean canExecute() 测试应用程序是否可以执行此抽象路径名表示的文件

boolean canRead() 测试应用程序是否可以读取此抽象路径名表示的文件。

boolean canWrite() 测试应用程序是否可以修改此抽象路径名表示的文件。

int compareTo(File pathname) 按字母顺序比较两个抽象路径名。

boolean equals(Object obj) 测试此抽象路径名与给定对象是否相等。

boolean exists() 测试此抽象路径名表示的文件或目录是否存在。

boolean isAbsolute() 测试此抽象路径名是否为绝对路径名。

boolean isDirectory() 测试此抽象路径名表示的文件是否是一个目录。

boolean isFile() 测试此抽象路径名表示的文件是否是一个标准文件。

boolean isHidden() 测试此抽象路径名指定的文件是否是一个隐藏文件。

注意:判断文件对象是否是文件或目录时,必须先通过exists()判断文件对象是否存在。

4.获取信息

 

File getAbsoluteFile() 返回此抽象路径名的绝对路径名形式。

String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串。

File getCanonicalFile() 返回此抽象路径名的规范形式。

String getCanonicalPath() 返回此抽象路径名的规范路径名字符串。

long getFreeSpace() 返回此抽象路径名指定的分区中未分配的字节数。

String getName() 返回由此抽象路径名表示的文件或目录的名称。

String getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null

File getParentFile() 返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null

String getPath() 将此抽象路径名转换为一个路径名字符串。

long getTotalSpace() 返回此抽象路径名指定的分区大小。

long getUsableSpace() 返回此抽象路径名指定的分区上可用于此虚拟机的字节数。

long lastModified() 返回此抽象路径名表示的文件最后一次被修改的时间。

long length() 返回由此抽象路径名表示的文件的长度。

static File[]listRoots()列出可用的文件系统根也就是所有的盘符

String[] list() 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。

String[] list(FilenameFilter filter) 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。

File[] listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。

File[] listFiles(FileFilter filter) 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。

File[] listFiles(FilenameFilter filter)返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。

 

String[] list(FilenameFilter filter) 方法举例:只获取.java文件:

File f = new File("F:\\java_Example\\ff");

JavaFile jf = new JavaFile();

String[] str =jf.list(new FilenameFilter()

{

public boolean accept(File dir,String name)

{

return name.endsWith(".java");

}

});

for(String s : str)

{

System.out.println(s);

}

 

File[] listFiles() 方法举例:列出目录下所有内容,包括子目录

递归法:

public static void showDir(File dir)

{

System.out.println(dir);

File[] files = dir.listFiles();

for(int x=0; x<files.length; x++)

{

if(files[x].isDirectory())

showDir(files[x]);

else

System.out.println(files[x]);

}

}

 

1.18.11集合 Properties

Properties是集合体系和IO体系相结合的集合容器,该对象的特点:

可以用于键值对形式的配置文件。

其主要方法:

load(InputStream inStream)从输入流中读取属性列表(键和元素对)。

load(Reader reader)按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。

store(OutputStream out, String comments)以适合使用 load(InputStream)方法加载到 Properties 表中的格式,将此 Properties表中的属性列表(键和元素对)写入输出流。

store(Writer writer, String comments)以适合使用 load(Reader)方法的格式,将此 Properties表中的属性列表(键和元素对)写入输出字符。

 

1.18.12打印流PrintWriterPrintStream

打印流提供了打印方法,可以将各种数据类型的数据都原样打印。构造函数中也提供了可以把文件对象、字符串路径文件名、指定字符集、输出流等作为参数传递。

 

1.18.13序列流 SequenceInputStream

对多个流进行合并。

表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

 

1.18.14对象流 ObjectInputStreamObjectOutputStream

ObjectOutputStream Java对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。

只能将支持 java.io.Serializable接口的对象写入流中。每个 serializable对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。

注意:在自定义类中静态static成员不会被序列化也就是不会被持久存储,如果想把非静态成员也不被序列化时可以在成员前加一个修饰符:transient;还可在类中自定义UID号:static final long serialVersionUID = 42LUID号);

 

1.18.15管道流 PipedInputStreamPipedOutputStream

可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream对象,并由其他线程从连接的 PipedInputStream读取。不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁。如果某个线程正从连接的管道输入流中读取数据字节,但该线程不再处于活动状态,则该管道被视为处于毁坏状态。

 

1.18.16包中的随机访问文件 RandomAccessFile

随机访问文件,自身具备读写的方法,内部封装了一个数组通过指针对数组的元素进行操作,还可以通过skipBytes(int x); seek(int x)来获取指针位置和设置指针位置。

构造函数:

RandomAccessFile(File file, String mode)创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File参数指定。

RandomAccessFile(String name, String mode)创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。

此类只可以操作文件,而且还有固定的模式mode

含意

"r"以只读方式打开。调用结果对象的任何 write方法都将导致抛出 IOException

"rw"打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。

"rws"打开以便读取和写入,对于 "rw",还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。

"rwd"打开以便读取和写入,对于 "rw",还要求对文件内容的每个更新都同步写入到底层存储设备。

 

此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek方法设置。

通常,如果此类中的所有读取例程在读取所需数量的字节之前已到达文件末尾,则抛出 EOFException(是一种 IOException)。如果由于某些原因无法读取任何字节,而不是在读取所需数量的字节之前已到达文件末尾,则抛出 IOException,而不是 EOFException。需要特别指出的是,如果流已被关闭,则可能抛出 IOException

 

 

1.18.17操作基本数据类型的流

DataInputStreamDataOutputStream

需要注意的是:writeUTF(String str)方法使用 UTF-8修改版编码,所以在读取时同样也需要使用此编码因此应使用readUTF()方法与之对应。

1.18.18操作字节数组的流

ByteArrayInputStreamByteArrayOutputStream

ByteArrayInputStream包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read方法要提供的下一个字节。在构造时需要接收数据源,数据源是一个字节数组。

ByteArrayOutputStream此类实现了一个输出流,其中的数据被写入一个 byte数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() toString()获取数据。在构造时不用定义数据目的地,因为应对象中已内部封装了可变长度的字节数组。

关闭无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException

 

1.18.19操作字符数组的流

CharArrayInputStreamCharArrayOutputStream

 

1.18.20操作字符串的流

StringReaderStringWriter

 

1.19编码表(字符集)

ASCII:美国标准信息交换码

用一个字节的7位表示

ISO8859-1:拉丁码表、欧洲码表

用一个字节的8位表示

GB2312:中国的中文编码表

GBK:中国的中文编码表升级版

用两个字节来表示一个汉字

Unicode:国际校准码表。

所有文字都用两个字节来表示,java语言使用的就是Unicode

UTF-8:最多用三个字节来表示一个字符。

 

编码:字符串变成字节数组

String -->byte[]str.getBytes(字符集名);

解码:字节数组变成字符串

Byte[] -->Stringnew Strnig(byte[],字符集名);

 

注意:1,当解码时指定字符集错了时可以通过原编码时的字符集进行再编码后再解码解决。

但是GBKUTF-8之间转错后不能通过此方法解决,因为两个编码表中都存在中文。

2,图片的字符集是UTF-16BE ,UTF-16LE

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics