黑马程序员 IO流-->其它流对象以及一些重要类

------- android培训java培训、期待与您交流! ----------

  File类


一、简单介绍:File类是IO包中的一个重要类,在对文件的操作中会频繁的用到。File对象就是对

文件和目录名的抽象表示形式,可以通过File对象对文件或目录的属性信息进行操作,File对象也

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

二、File类的一些常见方法:

1>创建文件  boolean createNewFile();

在指定位置创建一个文件,如果文件已经存在,不重新创建,并返回false。

2>创建文件夹  boolean mkdir()和boolean mkdirs();

mkdir只能创建一级目录,而mkdirs可以创建多级目录;

例如:File file = new File("abc\\ab\\a"),ab文件夹不存在的情况下,使用file.mkdir()会返回false。

3>删除  boolean delete()和void deleteOnExit();

使用delete删除失败时返回false,deleteOnExit()是在虚拟机终止时,请求删除此抽象路径名表示的

文件或目录。

4>判断  boolean exists():判断文件是否存在,在判断File对象是文件或者目录时,必须先判断该对

象封装的内容是否存在;boolean isDirectory():判断此抽象路径名表示的文件是否是一个目录;

boolean isFile():判断此抽象路径名表示的文件是否是一个标准文件;boolean isHidden():判断文

件是不是隐藏的。

5>获取信息  getName():返回此抽象路径名表示的文件或目录的名字;getPath();获取文件路径(

封装什么路径获取什么样的路径);getParent();返回绝对路径中的父目录;getAbsolutePath();

获取绝对路径。

三、File类的应用

1>把d:\java目录下的所有.java文件改为.jad文件。

这个练习用到了File类的File[] listFiles(FilenameFilter filter)和boolean renameTo(File dest);

其中listFiles返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和

目录。FilenameFilter是一个接口,实现此接口中的accept(File dir, String name)方法可以测试指定文

件是否包含在某一文件列表中。而renameTo是重新命名此抽象路径名表示的文件。

import java.io.File;
import java.io.FilenameFilter;

public class RenameDemo {

	public static void main(String[] args) {
		// 将给定路径名字符串转换为抽象路径名来创建一个新 File实例
		File file = new File("d:\\java");
		// 返回所有满足指定过滤器的文件
		File[] files = file.listFiles(new FilenameFilter() {

			@Override
			public boolean accept(File dir, String name) {
				// dir目录中的文件如果以.java为后缀名,则返回true
				return name.endsWith(".java");
			}
		});

		for (File oldFile : files) {
			// 获得.java文件的绝对路径
			String oldName = oldFile.getAbsolutePath();
			// 更改后缀名
			String newName = oldName.replace(".java", ".jad");
			// 重命名
			oldFile.renameTo(new File(newName));
		}
	}
}

2>列出指定目录下文件或者文件夹,包含子目录中的内容。

import java.io.File;

public class ListAllFileDemo {

	public static void main(String[] args) {
		// 封装目录
		File file = new File("d:\\exam");
		listAllFiles(file, 0);

	}

	/**
	 * 罗列出file下的所有文件,此方法中由于函数自身又调用了自身,用到了递归。 
	 * 用递归时应注意限定条件和递归的次数,以免造成内存溢出。
	 * 
	 * @param file
	 *            指定目录
	 * @param level
	 */
	public static void listAllFiles(File file, int level) {
		// 打印文件的名字
		System.out.println(getSpace(level) + file.getName());
		// 罗列出file下的所有文件和目录
		File[] childFiles = file.listFiles();
		if (childFiles.length != 0) {
			// 每往里一层,级别加1
			level++;
			for (File child : childFiles) {
				// 如果子文件仍为目录,那么调用函数自身,否则打印出文件名字
				if (child.isDirectory()) {
					listAllFiles(child, level);
				} else {
					System.out.println(getSpace(level) + child.getName());
				}
			}
		}
	}

	/**
	 * 获得level级前的空格距离
	 * 
	 * @param level
	 * @return
	 */
	private static String getSpace(int level) {
		StringBuilder builder = new StringBuilder();
		for (int i = 0; i < level; i++) {
			builder.append(" ");
		}
		return builder.toString();
	}
}

3>将一个指定目录下的所有java文件的绝对路径存储到一个文本文件中。

步骤:--建立一个java文件列表文件;

          --对指定的目录进行递归,获取所有的java文件的路径;

          --将这些路径存储到集合中;

          --将集合中的数据写入文件中。

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class JavaFilePath {

	public static void main(String[] args) {
		// 声明java文件路径集合
		List<String> javaPaths = new ArrayList<String>();
		// 指定要遍历的目录
		File dir = new File("d:\\exam");
		// 把指定目录中所有java文件的绝对路径存入集合中
		pathToList(javaPaths, dir);
		// java文件列表文件
		File javaListFile = new File("d:\\java.txt");
		// 把集合中的数据写入文件中
		writeToFile(javaPaths, javaListFile);
	}

	/**
	 * 把集合中的数据写入指定的文件中
	 * 
	 * @param paths
	 * @param javaListFile
	 */
	private static void writeToFile(List<String> paths, File javaListFile) {
		BufferedWriter bw = null;
		try {
			bw = new BufferedWriter(new FileWriter(javaListFile));
			for (String path : paths) {
				bw.write(path);
				bw.newLine();
				bw.flush();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				bw.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 遍历目录中的所有内容,如果子文件是目录,调用自身函数 
	 * 如果是文件并且后缀名为.java则把文件的绝对路径存入集合中
	 * 
	 * @param javaPaths
	 * @param dir
	 */
	private static void pathToList(List<String> javaPaths, File dir) {
		File[] files = dir.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				pathToList(javaPaths, file);
			} else if (file.getName().endsWith(".java")) {
				javaPaths.add(file.getAbsolutePath());
			}
		}
	}
}


 Properties类


一、简单介绍:Properties是HashTable的子类,也就是说它具备map集合的特点,而且它里面存

储的键值对都是字符串,不需要泛型。Properties是集合中和IO技术相结合的集合容器,该对象

可用于键值对形式的配置文件。在加载数据时,需要数据有固定格式,key=value。
二、Properties类的应用
1>设置的获取元素。
用到的stringPropertyNames()是获取所有的key值返回一个Set<String>集合。
import java.util.Properties;
import java.util.Set;

public class PropertiesDemo {

	public static void main(String[] args) {
		setAndGet();
	}

	/**
	 * 设置和获取Properties的元素
	 */
	private static void setAndGet() {
		Properties prop = new Properties();
		// 设置元素
		prop.setProperty("zhangsan", "20");
		prop.setProperty("lisi", "30");
		prop.setProperty("wangwu", "40");
		// 打印集合
		System.out.println(prop);
		// 获得键为lisi的元素的值并打印
		String value = prop.getProperty("lisi");
		System.out.println(value);
		// 设置键为lisi的值为"32"
		prop.setProperty("lisi", "32");
		// 遍历集合获得所有元素的key
		Set<String> keys = prop.stringPropertyNames();
		for (String key : keys) {
			System.out.println(key + ":" + prop.getProperty(key));
		}
	}
}

--------------------打印结果-----------------------

{zhangsan=20, lisi=30, wangwu=40}
30
zhangsan:20
lisi:32
wangwu:40

2>用Properties存取配置文件。
import java.io.*;
import java.util.Properties;

public class PropertiesDemo1 {

	public static void main(String[] args) {
		File file = new File("d:\\configuration.txt");
		method_1(file);
		method_2(file);
	}

	/**
	 * 将指定文件中的键值数据存储到集合中
	 * 
	 * @param file
	 */
	private static void method_1(File file) {
		Properties prop = new Properties();
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(file));
			String line = null;
			while ((line = br.readLine()) != null) {
				// 将文件中的每一行数据用"="分割
				String[] arr = line.split("=");
				// 等号左边作为键,右边作为值存入集合中
				prop.setProperty(arr[0], arr[1]);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		System.out.println(prop);
	}

	/**
	 * 使用Properties的方法存取配置文件
	 * 
	 * @param file
	 */
	private static void method_2(File file) {
		Properties prop = new Properties();
		FileInputStream fis = null;
		FileOutputStream fos = null;

		try {
			fis = new FileInputStream(file);
			// load方法的原理实际上就是method_1,把文件中的配置信息加载到集合中
			prop.load(fis);
			System.out.println(prop);

			prop.setProperty("zhangsan", "28");
			fos = new FileOutputStream(file);
			// 把集合中的数据存入文件中,第二个参数是注释,可写可不写
			prop.store(fos, null);
			System.out.println(prop);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

--------------------打印结果--------------------
method_1: {zhangsan=20, lisi=30, wangwu=40} 
method_2: {zhangsan=20, lisi=30, wangwu=40}
          {zhangsan=28, lisi=30, wangwu=40}

3>记录应用程序的运行次数,如果使用次数已到,给出注册提示。
思路:建立一个配置文件,用于记录该软件的使用次数。
import java.io.*;
import java.util.Properties;

public class PropertiesDemo2 {
	public static void main(String[] args) {
		File file = new File("d:\\count.ini");
		runCount(file);
	}

	/**
	 * 用文件记录程序运行的次数,用键值对的形式存储,这样便于阅读和操作数据
	 * 
	 * @param file
	 */
	private static void runCount(File file) {
		Properties prop = new Properties();
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			if (!file.exists()) {
				file.createNewFile();
			}
			fis = new FileInputStream(file);
			// 加载配置文件中的数据
			prop.load(fis);
			int count = 0;
			// 获得time的值,即运行的次数
			String value = prop.getProperty("time");
			if (value != null) {
				count = Integer.parseInt(value);
				// 如果程序运行超过3次,对用户作出提醒
				if (count >= 3) {
					System.out.println("使用次数已到,请注册!");
					return;
				}
			}
			// 每运行一次,count加1
			count++;
			// 设置集合中time的值
			prop.setProperty("time", "" + count);
			fos = new FileOutputStream(file);
			// 把集合中的数据重新存入文件中
			prop.store(fos, "");
			System.out.println(prop);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

 ---------------------打印结果---------------------
 第一次运行:{time=1}
 第二次运行:{time=2}
 第三次运行:{time=3}
 第四次运行:使用次数已到,请注册!
 第五次运行:使用次数已到,请注册!

 IO包中其它流对象-->打印流


打印流包括:PrintStream和PrintWriter,打印流可以直接操作输出流和文件,该流提供了打印
方法,可以将各种数据类型的数据都原样打印。它们的构造函数可以接收file对象、字符串路径、
字节输出流,PrintWriter还可以接收字符输出流。
import java.io.*;

public class PrintStreamDemo {

	public static void main(String[] args) {
		// 源为键盘录入
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String line = null;
		// 使用打印流写到控制台,第二个参数为true时,则 println、printf或 format方法将刷新输出缓冲区
		PrintWriter pw = new PrintWriter(System.out, true);
		try {
			while ((line = br.readLine()) != null) {
				if ("over".equals(line)) {
					break;
				}
				pw.println((line));
				// pw.flush();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 序列流-->SequenceInputStream


序列流SequenceInputStream表示其他输入流的逻辑串联,它从输入流的有序集合开始,并从第一
个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的
最后一个输入流的文件末尾为止。
练习1:将多个读取流合并成一个读取流,并把数据写入一个指定的文件中。
import java.io.*;
import java.util.Enumeration;
import java.util.Vector;

public class SequenceStreamDemo {

	public static void main(String[] args) {
		FileInputStream fis1 = null;
		FileInputStream fis2 = null;
		FileInputStream fis3 = null;
		// 创建需要串联的流对象
		try {
			fis1 = new FileInputStream("d:\\1.txt");
			fis2 = new FileInputStream("d:\\2.txt");
			fis3 = new FileInputStream("d:\\3.txt");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		// method_1(fis1, fis2);
		method_1(fis1, fis2, fis3);
	}

	/**
	 * 由于参数的个数不确定,使用java5的新特性,可变参数
	 * 
	 * @param streams
	 */
	private static void method_1(InputStream... streams) {
		// 声明合并流
		SequenceInputStream sis = null;

		File newFile = new File("d:\\new.txt");
		FileOutputStream fos = null;
		// 如果参数的个数为2,那么直接使用SequenceInputStream(InputStream s1, InputStream s2)
		// 构造方法
		if (streams.length == 2) {
			sis = new SequenceInputStream(streams[0], streams[1]);
		} else {
			// 把传入的流对象放入集合中
			Vector<InputStream> vector = new Vector<InputStream>();
			for (InputStream in : streams) {
				vector.add(in);
			}
			Enumeration<InputStream> en = vector.elements();
			// 个数大于2,用SequenceInputStream(Enumeration<? extends InputStream> e)
			sis = new SequenceInputStream(en);
		}
		try {
			// 把合并流中的所有数据写入指定的文件中
			fos = new FileOutputStream(newFile);
			int len = 0;
			byte[] buf = new byte[1024];
			while ((len = sis.read(buf)) != -1) {
				fos.write(buf, 0, len);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (sis != null) {
				try {
					sis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

练习2:切割文件,即把文件分割成几部分,再把这几部分合并到一个新文件。
import java.io.*;
import java.util.*;

public class SplitFile {

	public static void main(String[] args) {
		// 源(需要切割的文件)
		File file = new File("d:\\abc.jpg");
		splitFile(file);
		// 目的(合并成的文件)
		File newFile = new File("d:\\abc_new.jpg");
		FileInputStream fis1 = null;
		FileInputStream fis2 = null;
		FileInputStream fis3 = null;
		// 创建需要合并的流对象
		try {
			fis1 = new FileInputStream("d:\\1.part");
			fis2 = new FileInputStream("d:\\2.part");
			fis3 = new FileInputStream("d:\\3.part");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		marge(newFile, fis1, fis2, fis3);

	}

	/**
	 * 切割指定的文件
	 * 
	 * @param file
	 */
	private static void splitFile(File file) {
		int part = 0;
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			fis = new FileInputStream(file);
			byte[] buf = new byte[1024 * 1024];
			int len = 0;
			// 读入缓冲区1M数据(如果文件大小不足1M,则读入len个字节)
			while ((len = fis.read(buf)) != -1) {
				fos = new FileOutputStream("d:\\" + (++part) + ".part");
				// 把缓冲区中的数据写入一个文件
				fos.write(buf, 0, len);
				fos.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 由于参数的个数不确定,使用java5的新特性,可变参数
	 * 
	 * @param newFile
	 *            合并数据到新文件
	 * 
	 * @param streams
	 */
	private static void marge(File newFile, InputStream... streams) {
		// 声明合并流
		SequenceInputStream sis = null;
		FileOutputStream fos = null;
		// 如果参数的个数为2,那么直接使用SequenceInputStream(InputStream s1, InputStream s2)
		// 构造方法
		if (streams.length == 2) {
			sis = new SequenceInputStream(streams[0], streams[1]);
		} else {
			// 把传入的流对象放入集合中
			Vector<InputStream> vector = new Vector<InputStream>();
			for (InputStream in : streams) {
				vector.add(in);
			}
			Enumeration<InputStream> en = vector.elements();
			// 个数大于2,用SequenceInputStream(Enumeration<? extends InputStream> e)
			sis = new SequenceInputStream(en);
		}
		try {
			// 把合并流中的所有数据写入指定的文件中
			fos = new FileOutputStream(newFile);
			int len = 0;
			byte[] buf = new byte[1024];
			while ((len = sis.read(buf)) != -1) {
				fos.write(buf, 0, len);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (sis != null) {
				try {
					sis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

 操作对象的流-->ObjectInputStream、ObjectOutputStream


简单介绍:ObjectInputStream和ObjectOutputStream是可以直接操作对象的流。
ObjectOutputStream将Java对象的基本数据类型和图形写入OutputStream。可以使用
ObjectInputStream读取(重构)对象。通过在流中使用文件实现对象的持久化。被操作的对象
必须实现了Serializable接口。
练习:实现对象的持久化。
import java.io.*;

public class ObjectStreamDemo {

	public static void main(String[] args) {
		File file = new File("d:\\person.object");
		writeObj(file);
		readObj(file);
	}

	/**
	 * 读取对象
	 * 
	 * @param file
	 */
	private static void readObj(File file) {
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(new FileInputStream(file));
			// 从ObjectInputStream读取对象
			Person person = (Person) ois.readObject();
			System.out.println(person);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (ois != null) {
				try {
					ois.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 写入对象
	 * 
	 * @param file
	 */
	private static void writeObj(File file) {
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream(file));
			// 将指定的对象写入ObjectOutputStream
			oos.writeObject(new Person("zhangsan", 24));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (oos != null) {
				try {
					oos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

/**
 * 实现Serializable接口以启用其序列化功能,序列化接口没有方法或字段,仅用于标识此类可序列化
 * 
 */
class Person implements Serializable {
	/**
	 * 序列化运行时使用一个称为serialVersionUID的版本号与每个可序列化类相关联, 如果接收
	 * 者加载的该对象的类的serialVersionUID与对应的发送者的类的版本号不同,则反序列化将
	 * 会导致InvalidClassException。
	 * 可序列化类可以通过声明名为"serialVersionUID"的字段(该字段必须是静态 (static)、
	 * 最终(final)的long型字段)显式声明自己的serialVersionUID,如果可序列化类未显式
	 * 声明,则序列化运行时将基于该类的各个方面计算该类的默认serialVersionUID值。
	 */
	private static final long serialVersionUID = 100L;
	String name;
	// int age;
	// 被transient修饰的变量不会被序列化
	transient int age;

	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}

	@Override
	public String toString() {
		return name + ":" + age;
	}

}

-----------------------打印结果----------------------
 age的声明前不加transient:zhangsan:24
 age的声明前加transient:zhangsan:0

 管道流-->PipedInputStream、PipedOutputStream


可以将管道输入流和输出流连接来创建通信管道。管道输出流是管道的发送端。通常,数据由某个
线程写入PipedOutputStream对象,并由其他线程从连接的PipedInputStream读取。不建议对这两
个对象使用单个线程,因为这样可能会造成该线程死锁。
练习:在多线程中使用管道流读写数据。
import java.io.*;

public class PipedStreamDemo {

	public static void main(String[] args) {
		PipedOutputStream pos = new PipedOutputStream();
		PipedInputStream pis = new PipedInputStream();
		try {
			// 用一个管道输出流对象连接一个管道输入流对象
			pos.connect(pis);
			// 开启读数据线程和写数据线程
			new ReadThread(pis).start();
			new WriteThread(pos).start();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

class ReadThread extends Thread {
	private PipedInputStream in;

	public ReadThread(PipedInputStream in) {
		this.in = in;
	}

	@Override
	public void run() {
		int len = 0;
		byte[] buf = new byte[1024];

		try {
			// 从管道输入流中读取数据,没有数据时,该方法处于阻塞状态
			len = in.read(buf);
			String s = new String(buf, 0, len);
			System.out.println(s);
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

class WriteThread extends Thread {
	private PipedOutputStream out;

	public WriteThread(PipedOutputStream out) {
		this.out = out;

	}

	@Override
	public void run() {
		try {
			// 往管道输出流写数据
			out.write("data".getBytes());
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 随机访问文件-->RandomAccessFile


RandomAccessFile-随机访问文件类,它直接继承自Object,是IO包中的成员,自身具备读和写的
功能,也就是说它的最终实现原理是内部封装了FileInputStream和FileOutputStream。这个类的内
部封装了一个数组,通过指针对数组中的元素进行操作,可以通过getFilePointer获得当前指针的位
置,也可以通过seek改变指针的位置。它主要通过skipBytes(int x),seek(int x)来达到对文件的随
机访问。
注意:该类只能操作文件,RandomAccessFile的构造方法接收两个参数,第一个参数为要操作的文
件或文件路径的字符串表达形式,第二个参数为指定用以打开文件的访问模式,包括"r","rw","rws",
"rwd",如果模式为只读 "r",不会创建文件,只能读取一个已存在的文件,如果文件不存在,则会出
现异常,如果模式为读写 "rw",那么该对象操作的文件如果不存在会自动创建,如果存在也不会覆盖,
而是直接对此文件进行相应的读写操作。
练习:使用RandomAccessFile对象对文件进行读写操作。
import java.io.*;

public class RandomAccessFileDemo {

	public static void main(String[] args) {
		RandomAccessFile writeRAF = null;
		RandomAccessFile readRAF = null;
		try {
			// 随机访问文件对象,第一个参数是需要访问的文件,第二个参数定义了对文件的读写权限
			writeRAF = new RandomAccessFile("d:\\random.txt", "rw");
			readRAF = new RandomAccessFile("d:\\random.txt", "r");
			writeFile(writeRAF);
			// writeFile(writeRAF, 8 * 3);
			// readFile(readRAF);
			readFile(readRAF, 8);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 使用RandomAccessFile读取文件中的数据
	 * 
	 * @param accessFile
	 * @throws IOException
	 */
	private static void readFile(RandomAccessFile accessFile)
			throws IOException {
		byte[] buf = new byte[4];
		accessFile.read(buf);
		String name = new String(buf);

		int age = accessFile.readInt();

		System.out.println("name=" + name + "; age=" + age);

		accessFile.close();
	}

	/**
	 * 使用RandomAccessFile随机读取文件中的数据
	 * 
	 * @param accessFile
	 * @param index
	 *            设置到此文件开头测量到的文件指针偏移量
	 * @throws IOException
	 */
	private static void readFile(RandomAccessFile accessFile, int index)
			throws IOException {
		accessFile.seek(index);
		// 跳过index个字节
		// accessFile.skipBytes(index);
		readFile(accessFile);
	}

	/**
	 * 使用RandomAccessFile向文件中写数据
	 * 
	 * @param accessFile
	 * @throws IOException
	 */
	private static void writeFile(RandomAccessFile accessFile)
			throws IOException {
		accessFile.write("张三".getBytes());
		accessFile.writeInt(45);

		accessFile.write("李四".getBytes());
		accessFile.writeInt(97);

		accessFile.close();
	}

	/**
	 * 使用RandomAccessFile向文件中某个位置开始写数据,或修改已有的数据
	 * 
	 * @param accessFile
	 * @param index
	 * @throws IOException
	 */
	private static void writeFile(RandomAccessFile accessFile, int index)
			throws IOException {
		accessFile.seek(index);
		// accessFile.skipBytes(8);
		writeFile(accessFile);
	}
}


------------------------------打印结果-------------------------------
 调用readFile(readRAF)的打印结果:name=张三; age=45
 调用readFile(readRAF, 8)的打印结果:name=李四; age=97

 操作基本数据类型的流-->DataInputStream、DataOutputStream


DataInputStream和DataOutputStream是可以用于操作基本数据类型数据的流对象。数据输入流允许
应用程序以与机器无关方式从底层输入流中读取基本Java数据类型。数据输出流允许应用程序以适当
方式将基本Java数据类型写入输出流中。
练习:使用DataOutputStream和DataInputStream写入和读取基本数据类型数据。
import java.io.*;

public class DataStreamDemo {

	public static void main(String[] args) {
		writeData();
		readData();
		writeUTFData();
		readUTFData();
	}

	private static void writeData() {
		try {
			DataOutputStream dos = new DataOutputStream(new FileOutputStream(
					"d:\\data.txt"));
			// 将一个boolean值以1-byte值形式写入基础输出流
			dos.writeBoolean(true);
			// 将一个int值以4-byte值形式写入基础输出流
			dos.writeInt(782);
			// 使用Double类中的doubleToLongBits方法将double参数转换为一个long值,
			// 然后将该long值以8-byte值形式写入基础输出流
			dos.writeDouble(4237.3247);
			dos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void readData() {
		try {
			DataInputStream dis = new DataInputStream(new FileInputStream(
					"d:\\data.txt"));
			// 从所包含的输入流中读取此操作需要的字节
			// 读取数据的时候需要按照写入数据的顺序读取相应的字节数,否则读取到的数据与写入的数据不符
			boolean b = dis.readBoolean();
			int num = dis.readInt();
			double d = dis.readDouble();

			System.out.println("b=" + b + ", num=" + num + ", d=" + d);
			dis.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void writeUTFData() {
		try {
			DataOutputStream dos = new DataOutputStream(new FileOutputStream(
					"d:\\utfdata.txt"));
			//以与机器无关方式使用UTF-8修改版编码将一个字符串写入基础输出流
			//使用该方法写入的数据必须使用相对应的readUTF读取
			dos.writeUTF("你好");
			dos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void readUTFData() {
		try {
			DataInputStream dis = new DataInputStream(new FileInputStream(
					"d:\\utfdata.txt"));

			String utf = dis.readUTF();

			System.out.println(utf);
			dis.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

--------------------------打印结果---------------------------
b=true, num=782, d=4237.3247
你好

 ByteArrayInputStream、ByteArrayOutputStream


用于操作字节数组的流对象。ByteArrayInputStream在构造的时候,需要接收数据源,而且数据源
是一个字节数组。ByteArrayOutputStream在构造的时候不用定义数据目的,因为该对象内部已经
封装了一个可变长度的字节数组,该数组就是数据目的。
注意:因为这两个流对象操作的都是数组,没有使用系统资源,所以不需要关闭,此类中的方法在
关闭此流后仍可被调用,而不会产生任何IOException。
练习:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

public class ByteArrayStreamDemo {

	public static void main(String[] args) {
		// 数据源
		ByteArrayInputStream bais = new ByteArrayInputStream(
				"abcdefgh".getBytes());
		// 数据目的
		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		// 这个方法可以将此byte数组输出流的全部内容写入到指定的输出流参数中
		// baos.writeTo(new FileOutputStream("d:\\byte.txt"));
		int b = 0;
		while ((b = bais.read()) != -1) {
			baos.write(b);
		}
		System.out.println(baos.toString());
	}
}

 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值