您的位置:首页 > 编程语言 > Java开发

Java基础之IO流知识点总结三

2014-12-01 21:02 701 查看
File类:
该类的出现是对文件系统中的文件以及文件夹进行对象的封装。可以通过对象的思想来操作文件以及文件夹。
 
1.  构造函数:
File(String filename):将一个字符串路径(相对或者绝对)封装成File对象,该路径是可以存在的,也是可以不存在的。
File(Stringparent,String child);
File(Fileparent,String child);
2.  特别的字段:separator:跨平台的目录分隔符
eg.File file = newFile(“C:”+File.separator+”abc”+File.separator+”a.txt”);
 
3.  常见方法:
1)  创建:
boolean createNewFile() throwsIOException:创建文件,如果被创建的文件已经被创建,则不再创建。
boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。
2)  删除:
boolean delete():可用于删除文件或者文件夹。
注意:对于文件夹只能删除不带内容的空文件夹;则对于带内容的文件夹,不可以直接删除,必须要从里往外依次删除。
           void deleteOnExit():删除动作将在系统完成时触发。无论是否发生异常,系统在退出时执行删除动作。
3)  判断:
           boolean canExecute():该文件是否能执行。
           boolean canWrite():是否是可写文件
           boolean canRead():是否是可读文件
 
           boolean exists():判断文件或者文件夹是否存在。
           boolean isFile():判断File对象中封装的是否是文件。
           boolean isDirectory():判断File对象中封装的是文件夹。
           boolean isHidden():判断文件或者文件夹是否隐藏,在获取硬盘文件或者文件夹时,对于系统目录中的文件,java是无法访 问的。所以遍历,可以避免遍历隐藏文件。
4)  获取:
           String getName():获取文件或者文件夹的名称。
           String getPath():File对象中封装的路径是什么,获取的就是什么。
           String getAbsolutePath():无论File对象中封装的路径是什么,获取的都是绝对路径。
           String getAbsoluteFile():也返回绝对路径,但是把绝对路径封装成了对象。
           getParent():获取File对象封装文件或者文件夹的父目录。
            注意:如果封装的相对路径,那么返回的是null;
           long length():获取文件大小。
           long lastModified():获取文件或者文件最后一次修改的时间
           static File[] listRoots():获取的是被系统所用的有效盘符。
           string[] list():获取指定目录下当前的文件以及文件夹名称。
           string[] list(Filenamefilter): 可以根据指定的过滤器,过滤后的文件及文件夹名称。
File[] listFiles():获取指定目录下的文件以及文件夹对象。
5)  重命名:
           renameTo(File):
File f1 = newFile("c:\\a.txt");
File f2 = newFile("c:\\b.txt");
f1.renameTo(f2);//将c盘下的a.txt文件改名为b.txt文件。

例子1:File类的基本方法的使用。

package cn.itheima.day04;
/**
* File类的常见方法:
*    1.创建
*       boolean createNewFile() throws IOException
*       特点:创建文件,如果被创建的文件已经被创建,则
*            不再被创建。和输出流对象不一样,输出流对象
*            一建立创建文件,而且文件已经存在回覆盖。
*       boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。

*    2.删除
*       boolean delete():可用于删除文件或者文件将夹。
*                        如果文件中有内容,是直接删除删除不掉的。
*                        删除失败返回false
*       void deleteOnExit():删除动作将在系统完成时触发。
*                           无论是否发生异常,系统在退出时执行删除动作。
*    3.判断
*       boolean exists():文件是否存在。
*       boolean isFile():判断File对象中封装的是否是文件。
boolean isDirectory():判断File对象中封装的是文件夹。
boolean isHidden():判断文件或者文件夹是否隐藏,在获取硬盘文件或者文件夹时,对于系统目录中的文件,java是无法访问的。所以遍历,可以避免遍历隐藏文件。
*       String getName():获取文件或者文件夹的名称。
String getPath():File对象中封装的路径是什么,获取的就是什么。
String getAbsolutePath():无论File对象中封装的路径是什么,获取的都是绝对路径。
String getAbsoluteFile():也返回绝对路径,但是把绝对路径封装成了对象。
getParent():获取File对象封装文件或者文件夹的父目录。
注意:如果封装的相对路径,那么返回的是null;
long length():获取文件大小。
long lastModified():获取文件或者文件最后一次修改的时间
static File[] listRoots():获取的是被系统所用的有效盘符。
string[] list():获取指定目录下当前的文件以及文件夹名称。
string[] list(Filenamefilter): 可以根据指定的过滤器,过滤后的文件及文件夹名称。
File[] listFiles():获取指定目录下的文件以及文件夹对象。
重命名:
renameTo(File):
File f1 = new File("c:\\a.txt");
File f2 = new File("c:\\b.txt");
f1.renameTo(f2);//将c盘下的a.txt文件改名为b.txt文件。
*/
import java.io.File;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) throws IOException {
consMethod();
//method_1();
//method_2();
//method_3();
method_5();
}
public static void method_5(){
File f1 = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04\\file.txt");
File f2 = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04\\file_copy.txt");
sop("rename"+f1.renameTo(f2));
}
public static void method_3(){

18aa5
File f1 = new File("a.txt");
sop("path:"+f1.getPath());
sop("AbsolutePath:"+f1.getAbsolutePath());
//该方法返回的是绝对路径下的付目录,如果获取相对路径,返回null
//如果相对路径中有上一层目录,那么该目录就是返回结果。
sop("parent:"+f1.getParent());
}
public static void method_2(){
File file = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04\\file.txt");
sop("execute:"+file.canExecute());
sop("exists:"+file.exists());
File dir = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04\\wang\\abc\\dd");
//System.out.println("mkdir:"+dir.mkdir());  //返回最多一级文件夹
sop("mkdirs:"+dir.mkdirs());   //返回多级文件夹
//注意:对一个文件对象或者文件夹判断是它是文件还是文件夹时,此时,
//文件必须是存在的,通过exists()方法判断。
sop("file:"+file.isFile());   //判断是否为文件
sop("dir:"+dir.isDirectory());   //判断是否为文件夹
sop("absolute:"+file.isAbsolute());   //判断是否为绝对路径
}
public static void method_1() throws IOException{
File file = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04\\file.txt");
File deletefile = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04\\deletefile.txt");
sop("create:"+file.createNewFile());
sop("delete:"+deletefile.delete());
}
//创建File对象
public static void consMethod(){
//将a.txt封装成file对象,可以将已有的和未出现的文件及文件夹封装成对象
File f1 = new File("a.txt");
//第二种方式(想操作的目录下的文件时可以变化的)
File f2 = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04","b.txt");
//第三种方式
File d = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04");
File f3 = new File(d,"c.txt");
//separator跨平台的分隔符
File f4= new File("F:"+File.separator+"Javajichu"+File.separator+"JavaLianXi"                       +File.separator+"src"+File.separator+"cn"+File.separator+"itheima"
+File.separator+"day04"+File.separator+"e.txt");   		sop("f1="+f1);
sop("f2="+f2);
sop("f3="+f3);
sop("f4="+f4);
}
public static void sop(Object obj){
System.out.println(obj);
}
}


递归:
其实就是在使用一个功能过程中,又对该功能有需求。就出现了函数自身调用自身。
注意:
1,一定要限定条件,否则内存溢出。
2,使用递归时,调用次数不要过多,否则也会出现内存溢出。

例子2:想要列出指定目录下的文件以及文件夹中的文件(子文件)。

package cn.itheima.day04;
import java.io.File;
/**
* 列出指定文件目录下的文件或者文件夹,包含子目录的内容,
* 也就是列出该文件下的所有内容
*
* 因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。
* 在列出的目录过程中列出的还是目录,还可以再次调用本功能,也就是
* ,函数自身调用自身,则我们称这种方式为递归。
*
* 递归要限定的条件是:
*    1.要有限定条件。
*    2.使用递归时,调用次数不要过多,否则也会出现内存溢出。
* @author wl-pc
*/
public class FileDemo3 {
public static void main(String[] args) {
File dir = new File("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\");
showDir(dir,2);
//toBin(6);
//int n = getSum(10);
//sop("n="+n);
}
public static String getLevel(int level){
StringBuilder sb = new StringBuilder();
sb.append("|--");
for(int x = 0;x<level; x++){
//sb.append("|--");
sb.insert(0, "|  ");

}
return sb.toString();
}
//循环的列出文件夹中的文件,若文件夹中还有文件,则调用递归继续循环
public static void showDir(File dir,int level){
sop(getLevel(level)+dir.getName());
level++;
File[] files = dir.listFiles();
for (int x = 0;x<files.length; x++) {  //判断files是否为文件夹还是文件
if(files[x].isDirectory()){  //若files是文件夹,则应该接着进行列表显示
showDir(files[x],level);
}else{
sop(getLevel(level)+files[x]);
}
}
}
//求6的二进制数
public static void toBin(int num){
if(num>0){   //递归调用
toBin(num/2);
sop(num%2);	  //没次都先被执行
//num = num/2;
}
}
//求和
public static int getSum(int n){
if(n==1)
return 1;
return n+getSum(n-1);
}
public static void sop(Object obj){
System.out.println(obj);
}
}

例子3:删除一个带内容的目录。

package cn.itheima.day04;
import java.io.File;
/**
* 删除一个带内容的目录。
* 删除原理: 在windows删除目录是从里面往外.既然
*            从里往外删除,就需要用到了递归。
* @author wl-pc
*/
public class RemoveDir {
public static void main(String[] args) {
File file = new File("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\aa");
removeDir(file);
}
//删除文件夹
public static void removeDir(File dir) {
File[] files = dir.listFiles();
for (int x = 0; x < files.length; x++) {
if(files[x].isDirectory())
removeDir(files[x]);
else
System.out.println(files[x].toString()+":file:"+files[x].delete());
}
System.out.println(dir.toString()+":dir:"+dir.delete());
}
}

例子4:将一个指定目录下所有的java文件的绝对路径,存储到一个文本文件中,建立一个java文件的列表文件。

package cn.itheima.day04;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* 练习:
*    将一个指定目录下所有的java文件的绝对路径,存储到一个文本文件中。
*     建立一个java文件的列表文件。
* 思路:
*    1.对指定的目录进行递归。
*    2.获取在递归过程中所有java文件的路径。
*    3.将这些路径存储到集合中。
*    4.将集合中的数据写入到一个文件中。
* @author wl-pc
*/
public class JavaFileList {
public static void main(String[] args) throws IOException {
File dir = new File("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\");
List<File> list = new ArrayList<File>();
fileToList(dir,list);
System.out.println(list.size());
File file = new File("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\","javaList.txt");
writeToFile(list,file.toString());
}
public static void fileToList(File dir,List<File> list){
File[] files = dir.listFiles();
for (File file : files) {
if(file.isDirectory()){  //遍历目录,如果是目录则继续遍历。
fileToList(file, list);  //调用递归方法
}else{
if(file.getName().endsWith(".java")){  //将得到的java文件存储到集合中
list.add(file);
}
}
}
}
//数据持久化
public static void writeToFile(List<File> list,String javaListFile) throws IOException{
BufferedWriter bufw=null;
//javaListFile = "F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\";
try {
bufw = new BufferedWriter(new FileWriter(javaListFile));
for (File f : list) {
String path = f.getAbsolutePath();  //获取绝对路径
bufw.write(path);
bufw.newLine();
bufw.flush();
}
} catch (IOException e) {
throw e;
}finally{
try {
if(bufw!=null){
bufw.close();
}
} catch (IOException e) {
throw e;
}
}
}
}

例子5:利用Perperties类得到它里面存储的数据信息的值。

package cn.itheima.day04;
import java.util.Properties;
import java.util.Set;
/**
* Perperties是hashtable的子类,也就是说它具备了map集合的特点,而且
* 它里面存储的都是字符串,不需要泛型。
* 是集合中和IO技术相结合的集合容器。
* 该对象的特点可以用于键值对形式的配置文件。
* @author wl-pc
*/
public class PropertiesDemo {

public static void main(String[] args) {

setAndGet();
}
//设置和回去元素
public static void setAndGet(){
Properties properties = new Properties();
properties.setProperty("zhangsan", "30");  //设置属性,按键值对形式设置。
properties.setProperty("lisi", "39");
//System.out.println(properties);
String value = properties.getProperty("lisi");
//System.out.println(value);
properties.setProperty("lisi", "89");
Set<String> values = properties.stringPropertyNames();
for (String s : values) {
System.out.println(s+"::"+properties.getProperty(s));
}
}
}

例子6:利用Properties类读取文件中的数据(数据格式为:键=值)存储到集合中,并读取到控制台上,并且可以修改文件中的数据。

package cn.itheima.day04;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
/**
* Perperties是hashtable的子类,也就是说它具备了map集合的特点,而且
* 它里面存储的都是字符串,不需要泛型。
* 是集合中和IO技术相结合的集合容器。
* 该对象的特点可以用于键值对形式的配置文件。
* 在加载数据时需要数据要有固定的格式,通常是:键=值
* @author wl-pc
*/
public class PropertiesDemo {
public static void main(String[] args) throws IOException {
//setAndGet();
//method_1();
loadDemo();
}
public static void loadDemo(){
FileInputStream fis=null;
FileOutputStream fos=null;
try {
Properties properties = new Properties();
fis = new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\info.txt");
properties.load(fis);  //将流中的数据加载到集合中
//System.out.println(properties);
//properties.list(System.out);  //列出集合目录
properties.setProperty("wangwu", "99");  //改变内存中的数据的值,不改变文件中的值
fos = new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\info.txt");
properties.store(fos, "haha");   //将内存中的结果存储到一个流中,并且存储到一个文件中。
System.out.println(properties);
} catch (FileNotFoundException e) {
System.out.println(e.toString());
} catch (IOException e) {
System.out.println(e.toString());
}finally{
if(fis!=null){
try {
fis.close();
} catch (IOException e) {
System.out.println(e.toString());
}
}
if(fos!=null){
try {
fos.close();
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
}
//演示:如何将流中的数据存储到集合中
//想要将Info.xt中的键值数据存储到集合中的操作
/**
* 思路:
*    1.用一个流和info.txt文件关联。
*    2.读取一行数据,将该行数据用等号进行切割。
*    3.等号左边作为键,右边作为值,存入到Properties中即可。
* @throws IOException
*/
public static void method_1() throws IOException{
BufferedReader bufr=null;
try {
bufr = new BufferedReader(new FileReader("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\info.txt"));
String line = null;
Properties properties = new Properties();
while((line = bufr.readLine())!=null){
String[] arr = line.split("=");
System.out.println(arr[0]+"----"+arr[1]);
properties.setProperty(arr[0], arr[1]);
}
System.out.println(properties);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(bufr!=null){
bufr.close();
}
}
}
//设置和回去元素
public static void setAndGet(){
Properties properties = new Properties();
properties.setProperty("zhangsan", "30");  //设置属性,按键值对形式设置。
properties.setProperty("lisi", "39");
//System.out.println(properties);
String value = properties.getProperty("lisi");
//System.out.println(value);
properties.setProperty("lisi", "89");
Set<String> values = properties.stringPropertyNames();
for (String s : values) {
System.out.println(s+"::"+properties.getProperty(s));
}
}
}


例子7:用于记录应用程序运行的次数,如果使用次数已到,那么给出注册提示。

package cn.itheima.day04;
<pre>import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
/**
* 用于记录应用程序运行的次数。
* 如果使用次数已到,那么给出注册提示。
* 很容易想到使用计数器。
* 可是,该计数器定义在程序中,随着程序的运行而在内存中存在,并且进行自增,
* 可是,随着该应用程序的退出,该计数器也在内存中消失了。
* 下一次,在程序启动时,又重新开始从0记数了
* 这样不是我们想要的。
*
* 程序即使结束,该计数器的值也存在。
* 下次程序启动时也会先加载该计数器的值,并且技术加1后在重新存储起来,
*
* 所以要建立一个配置文件,用于记录该软件的使用次数。
* 该配置文件使用键值对的形式,这样便于阅读数据,操作数据。
* 键值对数据,是一个map集合。
* 数据是以文件的形式存储的,所以要使用io技术。
* 那么,map+io----->properties.
* 配置文件可以实现应用程序的数据的共享。
* @author wl-pc
*/
public class RunCount {
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
FileInputStream fis=null;
File file = new File("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\count.txt");
if(!file.exists())
file.createNewFile();
else
fis = new FileInputStream(file);
properties.load(fis);
int count = 0;
String value = properties.getProperty("time");
if(value!=null){
count = Integer.parseInt(value);
if(count>=5){
System.out.println("你好,你使用的次数已到,请注册后,使用。");
}
}
count++;
properties.setProperty("time", count+"");
FileOutputStream fos = new FileOutputStream(file);
properties.store(fos, "hello");
fos.close();
fis.close();
}
}



IO包中常见的对象:
字节流:
FileInputStream
FileOutputStream
BufferedInputStream
BufferedOutputStream
字符流:
          FilerReader
          FileWriter
          BufferedReader
          BufferedWriter
     转换流:
          InputStreamReader
          OutputStreamWriter
文件对象:
      File
打印流:
         PrintStream
         PrintWriter
注意:所有的带File的流对象都可以直接操作File对象。
IO包中的其他对象:
1.打印流
PrintStream:是一个字节打印流,System.out对应的类型就是PrintStream.
它的构造函数可以接收三种数据类型。
1.  字符串路径。
2.  File对象
3.  OutputStream
PrintWriter:是一个字符打印流,构造函数可以接收四种类型的值。
1.  字符串路径。
2.  File对象。
对于1.2类型的数据,还可以指定编码表。也就是字符集。
3.  OutputStream
4.  Writer
对于3.4类型的数据,可以指定自动刷新。
注意:该自动刷新的值为true时,只有三个方法可用:println,printf,format.
//如果想要既有自动刷新,又可执行编码。如何完成流对象的包装呢?
PrintWriter pw = new PrintWriter(newOutputStreamWriter(new FileOutputStream(“a.txt”)));
//如果想要提高效率,还要使用打印方法。
PrintWrterpw = newPrintWriter(new BufferdWriter(new OutputSteamWriter(new FileOutputStream("a.txt"),"utf-8")),true);


例子8:用打印流对象,用打印流接收用户在控制台输入的数据,然后用打印流输出到控制台上或者一个文件中

package cn.itheima.day04;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class PrintStreamDemo {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//PrintWriter out = new PrintWriter(System.out,true);
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\a.txt")),true);
String line=null;
while((line=br.readLine())!=null){
if("over".equals(line)){
break;
}
out.println(line.toUpperCase());
//out.flush();
}
out.close();
br.close();
}
}


2.序列流,也成合并流。
SequenceInputStream:
       特点:可以将多个读取流合并成一个流,这样操作起来很方便。
       原理:其实就是将每一个读取流对象存储到一个集合中,最后一个流对象结尾作为这个流的结尾。
两个构造函数:
1.  SequenceInputStream(InputStreamin1,InputStream in2):可以将两个读取流合并成一个流。
2.  SequenceInputStream(Enumeration<?Extents InputStream> en):可以将枚举中的多个流合并成一个流。

例子9:将3个读取流文件合并成一个读取流文件。

package cn.itheima.day04;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;
public class SequenceDemo {

public static void main(String[] args) throws IOException {
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\1.txt"));
v.add(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\2.txt"));
v.add(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\3.txt"));
Enumeration<FileInputStream> en = v.elements();   //枚举类型(将多个读取流合并成一个读取流)
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\4.txt");
byte[] buf = new byte[1024];
int len = 0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
}

作用:可以用于多个数据的合并。
注意:因为Enumeration是Vector中特有的取出方式。而Vector被ArrayList取代。所以要使用ArrayList集合效率更高一些。

那么如何获取Enumeration呢?

ArrayList<FileInputStream > al = new ArrayList<FileInputStream>();
for(int x=1; x<4; x++)
al.add(new FileInputStream(x+".txt"));
Iterator<FileInputStream> it = al.iterator();
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){
public boolean hasMoreElements(){
return it.hasNext();
}
public FileInputStream nextElement(){
return it.next();
}
};
//多个流就变成了一个流,这就是数据源。
SequenceInputStream sis = new SequenceInputStream(en);
//创建数据目的。
FileOutputStream fos = new FileOutputStream("4.txt");
byte[] buf = new byte[1024*4];
int len = 0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
sis.close();

例子10.文件的切割和合并。

package cn.itheima.day04;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Enumeration;
public class SplitFile {
public static void main(String[] args) throws IOException {
//splitFile();
merge();
}
//合并文件
public static void merge() throws IOException{
ArrayList<FileInputStream> aList = new ArrayList<FileInputStream>();
for(int x = 1;x<=4;x++){
aList.add(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\pic\\"+x+".part"));
}
final java.util.Iterator<FileInputStream> it = aList.iterator();
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() {
public boolean hasMoreElements() {
return it.hasNext();
}
public FileInputStream nextElement() {
return it.next();
}
};
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\pic\\0.png");
byte[] buf = new byte[1024];
int len=0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
//切割文件
public static void splitFile() throws IOException{
FileInputStream fis = new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\1.png");
FileOutputStream fos = null;
byte[] buf = new byte[1024*1024];
int len =0;
int count =1;
while((len=fis.read(buf))!=-1){
fos = new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\pic\\"+(count++)+".part");
fos.write(buf,0,len);
fos.close();
}
if(fos!=null){
fos.close();
}
fis.close();
}
}

操作对象的流:
ObjectInputStream
ObjectOutputStream 
可以通过这两个流对象直接操作已有的对象,并将对象进行本地持久化存储。存储后的对象可以进行网络传输。
两个对象的特有方法:
       ObjectInputStream
       Object readObject():该方法抛出异常:ClassNotFountException
       ObjectOutputStream
       void writeObject(Object):被写入的对象必须实现一个接口:Serializable,否则会抛出异常:NotSerializableException
Serializable:该接口其实就是一个没有方法的标记接口。
用于给类指定一个UID。该UID是通过类中的可序列化成员的数字签名运出来的一个long型的值。只要是这些成员没有变化,那么该值每次运算都一样。该值用于判断被序列化的对象和类文件是否兼容。如果被序列化的对象需要被不同的类版本所兼容。可以在类中自定义UID。
定义方式:static final long serialVersionUID = 42L;
注意:对应静态的成员变量,不会被序列化。
对应非静态也不想被序列化的成员而言,可以通过transient关键字修饰。

例子11.利用ObjectInputStream和ObjectOutputStream,写入和读取文件中的数据

package cn.itheima.day05;
import java.io.Serializable;
public class Person implements Serializable{
private static final long serialVersionUID = 42L;  //固定标示
private String name;
transient int age;   //对非静态的属性不想序列化的话,可以加一个关键字transient
static String country="cn";  //静态不能被序列化
public Person() {
super();
}
public Person(String name, int age,String country) {
super();
this.name = name;
this.age = age;
this.country=country;
}
public static String getCountry() {
return country;
}
public static void setCountry(String country) {
Person.country = country;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ",country=" + country + "]";
}
}

package cn.itheima.day05;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class ObjectStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//writeObj();
readObj();
}
//读文件中的持久化类
public static void readObj() throws  IOException, ClassNotFoundException{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\obj.txt"));
Person person = (Person)ois.readObject();
System.out.println(person);
ois.close();
}
//把类变成持久化
public static void writeObj() throws  IOException{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\obj.txt"));
oos.writeObject(new Person("lisi0",39,"china"));
oos.close();
}
}

管道流:
   PipedInputStream
   PipedOutputStream
   特点:
     读取管道流和写入管道流可以进行连接。
     连接的方式:
1.  通过两个流对象的构造函数。
2.  通过两个对象的connect方法。
 
     通常两个流在使用时,需要加入多线程技术,也就是让读写同时运行。
 注意:对于read方法。该方法是阻塞式的,也就是没有数据的情况,该方法会等

例子12.管道流的应用,用到多线程的知识。

package cn.itheima.day05;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
class Read implements Runnable {
private PipedInputStream in;
Read(PipedInputStream in){
this.in = in;
}
public void run() {
try {
byte[] buf = new byte[1024];
int len = 0;
System.out.println("读取前没有数据,阻塞");
len = in.read(buf);
System.out.println("读取到数据,阻塞结束");
String s = new String(buf,0,len);
System.out.println(s);
in.close();
} catch (IOException e) {
throw new RuntimeException("管道读取流失败");
}
}
}
class Writer implements Runnable {
private PipedOutputStream out;
public Writer(PipedOutputStream out) {
this.out = out;
}
public void run() {
try {
System.out.println("开始写入数据等待6秒后");
Thread.sleep(6000);
out.write("管道 来啦".getBytes());
out.close();
} catch (IOException e) {
throw new RuntimeException("管道输出流失败");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class PipedStream {
public static void main(String[] args) throws IOException {
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
in.connect(out);
Read r = new Read(in);
Writer w= new Writer(out);
new Thread(r).start();
new Thread(w).start();
}
}

RandomAccessFile类:
该类特点:该类不算IO体系中的子类,而是直接继承Object,但是它是IO包中的成员,因为它具备读和写功能,因为它内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过,getFilePointer获取指针位置,同时可以通过seek改变指针的位置。
其实完成读写的原理:内部封装了字节输入流和字节输出流。
通过构造函数,可以看出,该类只能操作文件,有局限性。
 而且操作文件还有模式(4种):r(只读)   rw(可读可写)   rws      rwd
而且该对象的构造函数要操作的文件不存在,会自动的创建,如果存在则不会覆盖。
如果模式是r: 则不会创建文件,会去读取一个已存在的文件,如果该文件不存在,则会出现异常。
如果模式是rw:操作的文件不存在,会自动创建,如果存在则不会原来的数据。

例子13:利用RandomAccessFile的seek()方法实现随机的读写和访问。

package cn.itheima.day05;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo {
public static void main(String[] args) throws IOException {
//writeFile();
//writerFile_2();
readFile();
//System.out.println(Integer.toBinaryString(258));
}

public static void readFile() throws IOException{
//RandomAccessFile可以随机的读写和访问。
RandomAccessFile raf=new  RandomAccessFile("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\ran.txt", "r");
//raf.write("haha".getBytes());被屏蔽
//调整对象中的指针,来在指定的位置读取和写入数据
//raf.seek(8*1);  //seek(long pos) 设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作(seek前后都能跳)

//跳过指定的字节数((-1,0)缺点:不能往回跳(不能往-1跳),只能往前跳(往0跳))
raf.skipBytes(8*3);
byte[] buf = new byte[4];
raf.read(buf);
String name = new String(buf);
System.out.println("name="+name);
int age = raf.readInt();
System.out.println("age="+age);
raf.close();
}
public static void writerFile_2(){
try {
RandomAccessFile raf = new RandomAccessFile("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\ran.txt", "rw");
//调整对象中的指针,来在指定的位置读取和写入数据
raf.seek(8*3);
raf.write("周期".getBytes());
raf.writeInt(103);
raf.close();

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writeFile(){
try {
RandomAccessFile raf = new RandomAccessFile("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\ran.txt", "rw");
raf.write("张三".getBytes());
raf.writeInt(97);
raf.write("王五".getBytes());
raf.writeInt(23);
raf.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

操作基本数据类型的流对象:DataInputStream.
DataInputStream:
   DatsInputStream(InputStream);
     它操作的基本数据类型的方法:
        Int readInt():一次读取四个字节,并将其转换成int值。
        booleanreadBoolean():一次读取一个字节。
        short readShort():
        longreadLong();
        String readUTF():按照utf-8修改版读取字符。注意,它只能读取writeUTF()写入的字符数据。
DataOutputStream:
     DataOutputStream(OutputStream):
操作基本数据类型的方法:
writeInt(int):一次写入四个字节。
注意和write(int)不同。write(int)只将该整数的最低一个8位写入。剩余三个8位丢弃。
writeBoolean(boolean);
writeShort(short);
writeLong(long);  
writeUTF(String):按照utf-8修改版将字符数据进行存储。只能通过readUTF读取。通常只要操作基本数据类型的数据。就需要通过DataStram进行包装。通常成对使用。


例子14:利用DataInputStream和DataOutputStream操作基本数据类型进行读写操作。

package cn.itheima.day05;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 可以用于操作基本数据类型的数据。
* @author wl-pc
*/
public class DataStreamDemo {
public static void main(String[] args) {
//writeData();
//readData();
//WriteUtfDemo();
readUtfDemo();
}
//读出utf格式的数据
public static void readUtfDemo(){
try {
DataInputStream dis = new DataInputStream(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\utfdata.txt"));
String value = dis.readUTF();
System.out.println(value);
dis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//写入utf格式的数据
public static void WriteUtfDemo(){
try {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\utfdata.txt"));
dos.writeUTF("小明");
dos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//读取数据
public static void readData(){
try {
DataInputStream dis = new DataInputStream(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\data.txt"));
int num = dis.readInt();
boolean b = dis.readBoolean();
double d = dis.readDouble();
System.out.println("num="+num);
System.out.println("b="+b);
System.out.println("d="+d);
dis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//写入数据
public static void writeData(){
try {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\data.txt"));
dos.writeInt(234);
dos.writeBoolean(true);
dos.writeDouble(98.03);
dos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}


操作数组的流对象:
1,操作字节数组
ByteArrayInputStream:特点:在构造时需要接收数据源,而且数据源是一个字节数组,
ByteArrayOutputStream 特点:在构造的时候,不用定义数组目的。因为该对象中已经内部封装了一个可变长度的字节数组。
toByteArray();
toString();
writeTo(OutputStream):输入内容到一个文件中。
因为这两个流对象都操作的是数组,并没有使用系统资源,所以,没有不用进行流的关闭。(即使流对象关闭,还是可以使用的。
在流---规律讲解时:
源设备:
         键盘 System.in     硬盘FileStream    内存ArrayStream
 目的:
         控制台System.out  硬盘FileStream     内存ArrayStream
用流的读写思想去操作数据。

例子15:ByteArrayInputStream和ByteArrayOutputStream来读写数据。

package cn.itheima.day05;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteArrayStream {
public static void main(String[] args) throws FileNotFoundException, IOException {
//明确数据源
ByteArrayInputStream bis = new ByteArrayInputStream("abcdefg".getBytes());
//明确数据目的
ByteArrayOutputStream bos = new ByteArrayOutputStream();
System.out.println(bos.size());
int by = 0;
while ((by = bis.read())!=-1) {
bos.write(by);
}
System.out.println(bos.size());
System.out.println(bos.toString());
bos.writeTo(new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\a.txt"));
}
}

2,操作字符数组。
CharArrayReader
CharArrayWriter
对于这些流,源是内存。目的也是内存。而且这些流并未调用系统资源。使用的就是内存中的数组。
所以这些在使用的时候不需要close。
操作数组的读取流在构造时,必须要明确一个数据源。所以要传入相对应的数组。
对于操作数组的写入流,在构造函数可以使用空参数。因为它内置了一个可变长度数组作为缓冲区。
编码转换:
在io中涉及到编码转换的流是转换流和打印流。但是打印流只有输出。在转换流中是可以指定编码表的。
默认情况下,都是本机默认的码表。GBK. 这个编码表怎么来的?System.getProperty("file.encoding");
常见码表:
ASCII:美国标准信息交换码。使用的是1个字节的7位来表示该表中的字符。
ISO8859-1:拉丁码表。使用1个字节来表示。
GB2312:简体中文码表。
GBK:简体中文码表,比GB2312融入更多的中文文件和符号。
unicode:国际标准码表。都用两个字节表示一个字符。
UTF-8:对unicode进行优化,每一个字节都加入了标识头。
编码转换:
    (String--àbyte[])
字符串-->字节数组:编码。
通过str.getBytes(charset);
(byte[]--àString)
字节数组-->字符串:解码。
通过String类的构造函数完成。new String(byte[],charset);
如果编错了,没救!
如果编对了,解错了,有可能还有救!
String s = "你好";
//编码。
byte[] b =s.getBytes("GBK");
//解码。
String s1 = newString(b,"iso8859-1");
System.out.println(s1);
 //想要还原。
/*
对s1先进行一次解码码表的编码。获取原字节数据。
然后在对原字节数据进行指定编码表的解码。
*/
byte[] b1 = s1.getBytes("iso8859-1");
String s2 = newString(b1,"gbk");
System.out.println(s2);//你好。
这种情况在tomcat服务器会出现。因为tomcat服务器默认是iso8859-1的编码表。所以客户端通过浏览器向服务端通过get提交方式提交中文数据时,服务端获取到会使用ISO8859-1进行中文数据的解码。会出现乱码。这时就必须要对获取的数据进行iso8859-1编码。然后在按照页面指定的编码表进行解码即可而对于post提交,这种方法也通用。但是post有更好的解决方式。
request.setCharacterEncoding("utf-8");即可。
所以建立客户端提交使用post提交方式。

例子16:写入和读出UTF-8编码和GBK编码的文件。
package cn.itheima.day05;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class EncodeStream {
public static void main(String[] args) {
//writeText();
readText();
}
public static void readText(){
try {
InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\gbk.txt"),"UTF-8");
int len = 0;
char[] buf = new char[10];
len = isr.read(buf);
String str = new String(buf,0,len);
System.out.println("str="+str);
isr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writeText(){
try {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\gbk.txt"),"UTF-8");
osw.write("你好");
osw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

例子17:中文乱码的解决方案。

package cn.itheima.day05;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class EncodeDemo {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "你好";
byte[] b1 = str.getBytes("GBK");   //编码
//System.out.println(Arrays.toString(b1));  //Arrays.toString(b1)  把数组变成字符串
String s1 = new String(b1,"ISO8859-1");   //要用指定编码表来解码
//s1进行ISO8859-1编码
byte[] b2 = s1.getBytes("ISO8859-1");
System.out.println(Arrays.toString(b2));  //Arrays.toString(b2)  把数组变成字符串
//解码
String s2 = new String(b2,"GBK");  //解决方案,就是 编译一次,在解码一次
//System.out.println(s1);
System.out.println(s2);
}
}

例子18:记事本敲“联通”,再次打开出现乱码的问题。查看“联通”的二进制数是符合GBK的编码,还是符合UTF-8的编码。

package cn.itheima.day05;
import java.io.UnsupportedEncodingException;
public class EncodeDemo2 {
public static void main(String[] args) throws UnsupportedEncodingException {
String s = "联通";
byte[] by = s.getBytes("GBK");
for (byte b : by) {
System.out.println(Integer.toBinaryString(b&255));
}
}
}

例子19:有五名学生,每个学生有3门课的成绩,从键盘上输入以上数据,(包括姓名,和三门课的成绩,输出格式为:zhangsan,30,40,60,并且计算出总成绩,并把学生信息和计算出的总分数,按从高到低的顺序存放到硬盘的文件上”studentScore.txt”)
分析:1.描述学生对象。
2.定义一个可操作学生对象的工具类。
思想:1.通过获得键盘上录入的一行数据,并将该行中的信息,取出封装成学生对象
2.因为学生对象有很多,就需要使用集合,因为学生的总分要排序,所以可以使用TreeSet
         3.将集合中的信息写入到一个文件中。

package cn.itheima.day05;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
class Student implements Comparable<Student>{
private String name;
private int ma,cn,en;
private int sum;

public String getName() {
return name;
}
public int getSum() {
return sum;
}
public int hashCode(){
return name.hashCode()+sum*78;
}
public boolean equals(Object obj){
if(!(obj instanceof Student))
throw new ClassCastException("类型不匹配");
Student s = (Student)obj;
return this.name.equals(s.name) && this.sum==s.sum;
}
@Override
public String toString() {
return "Student [name=" + name + ", ma=" + ma + ", cn=" + cn + ", en="
+ en + ", sum=" + sum + "]";
}
public Student(String name, int ma, int cn, int en) {
super();
this.name = name;
this.ma = ma;
this.cn = cn;
this.en = en;
sum = ma+cn+en;
}
@Override
public int compareTo(Student s) {
int num = new Integer(this.sum).compareTo(new Integer(s.sum));
if(num==0)
return this.name.compareTo(s.name);
return num;
}
}
class StudentInfoTool{
public static Set<Student> getStudents() throws IOException{
return getStudents(null);
}
public static Set<Student> getStudents(Comparator<Student> cmp) throws NumberFormatException, IOException{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line = null;
Set<Student> stus = null;
if(cmp==null){
stus=new TreeSet<Student>();
}else {
stus=new TreeSet<Student>(cmp);
}
while((line=bufr.readLine())!=null){
if("over".equals(line))
break;
String[] info= line.split(",");
Student stu = new Student(info[0], Integer.parseInt(info[1]), Integer.parseInt(info[2]), Integer.parseInt(info[3]));
stus.add(stu);
}
bufr.close();
return stus;

public static void writeFile(Set<Student> stus) throws IOException{
BufferedWriter bufw = new BufferedWriter(new FileWriter("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\studentinfo.txt"));
for (Student stu : stus) {
bufw.write(stu.toString()+"\t");
bufw.write(stu.getSum()+"");
bufw.newLine();
bufw.flush();
}
bufw.close();
}
}
public class StudentInfoTest {
public static void main(String[] args) throws NumberFormatException, IOException {
Comparator<Student> cmp = Collections.reverseOrder();
Set<Student> students = StudentInfoTool.getStudents(cmp);
StudentInfoTool.writeFile(students);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息