一、打印流
事实上,如果感觉要写好多%s、%d等字符麻烦,可以全部使用%s。
RandomAccessFile类的主要功能是完成随机读取功能,可以读取指定位置的内容。
打印流是输出信息最方便的类,主要包含字节打印流(PrintStream)和字符打印流(PrintWriter)。打印流提供了非常方便的打印功能,可以打印任何的数据类型,例如:小数、整数、字符串等。
1. PrintStream类的常用方法
// 通过一个File对象实例化PrintStream类
public PrintStream(File file) throws FileNotFoundException
// 接收OutputStream对象,实例化PrintStream类
public PrintStream(OutputStream out)
// 接收OutputStream对象,实例化PrintStream类,如果autoFlush为true时,自动刷新输出缓冲区
public PrintStream(OutputStream out, boolean autoFlush)
// 可以自动刷新,可以指定字符编码集
public PrintStream(OutputStream out, boolean autoFlush, String encoding) throws UnsupportedEncodingException
// 根据本地环境格式化输出
public PrintStream printf(String format, Object... args)
// 此方法被重载很多次,可以输出任意数据
public void print(Object obj)
// 此方法被重载很多次,可以输出任意数据后换行
2. 使用PrintStream输出信息
PrintStream printStream = null; // 声明打印流对象
printStream = new PrintStream(new FileOutputStream(""));
printStream.print("hello ");
printStream.print("world!!!");
printStream.print("1 + 1 = " + 2);
printStream.close();
3. 格式化输出
在JDK1.5之后,Java对PrintStream类进行了扩充,增加了格式化的输出方式,直接使用printf()方法就可以完成操作,但是在进行格式化输出时需要指定其输出数据类型。
NO | 字符 | 描述 |
1 | %s | 表示内容为字符串 |
2 | %d | 表示内容为整数 |
3 | %f | 表示内容为小数 |
4 | %c | 表示内容为字符 |
二、序列流,也称合并流
1. SequenceInputStream类的常用方法
// 初始化 SequenceInputStream,,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数
public SequenceInputStream(Enumeration<? extends InputStream> e)
// 返回文件的大小
public int available() throws IOException
2. 范例:将一个mp3文件按指定大小切割成几部分,然后根据切割后的文件还原出被切割的文件
①. 对文件按照一定的大小进行切割,需要指定源与目的,由于还要合成,所以必须要知道,文件切割了几份,文件切割前的名称。
/**
* 文件切割
*
* @param source
* 要切割的源文件
* @param target
* 切割后,碎文件保存的目录
* @throws IOException
*/
private static void slicingFile(File source, File target)
throws IOException {
// 读取源
FileInputStream fileInputStream = new FileInputStream(source);
// 目的
FileOutputStream fileOutputStream = null; // 由于切割后的碎文件不是一个,这里不能通过具体文件名实例化
byte[] bytes = new byte[1024 * 1024 * 2]; // 指定要切割的大小
int len = 0;
Properties properties = new Properties();
// 对指定的目录进行判断
if (!(target.exists() && target.isDirectory())) {
target.mkdir();
}
int count = 1; // 文件计数机,为了给切割后碎片命名
while ((len = fileInputStream.read(bytes)) != -1) {
fileOutputStream = new FileOutputStream(new File(target, (count++)
+ ".part"));
fileOutputStream.write(bytes, 0, len);
fileOutputStream.close();
}
// 将文件份数,文件名保存到.properties文件中
File config = new File(target, count + ".properties");
fileOutputStream = new FileOutputStream(config);
properties.setProperty("filename", source.getName());
properties.setProperty("partcount", String.valueOf(count));
properties.store(fileOutputStream, "");
fileOutputStream.close();
fileInputStream.close();
}
②. 文件合并,先要判断合并文件是否存在,目录中存在.properties文件,从.properties文件中拿到碎片的个数,与文件目录中比对,这些都正确之后,开始合并。
/**
* 合并文件
*
* @param target
* 要合并文件的目录
* @throws IOException
*/
private static void merge(File target) throws IOException {
// 判断该目录是否存在
if (!target.isDirectory())
throw new RuntimeException(target.getName() + "不存在");
// 判断该目录是否有配置文件
String[] files = target.list(new FilenameFilterByConfig());
if (files.length != 1)
throw new RuntimeException("后缀名为.properties的文件不存在或者不止一个");
File config = new File(target, files[0]);
FileInputStream fileInputStream = new FileInputStream(config);
Properties properties = new Properties();
properties.load(fileInputStream);
// 获取文件名称和碎片文件个数
String filename = properties.getProperty("filename");
int partcount = Integer.parseInt(properties.getProperty("partcount"));
// 对碎片文件进行过滤
File[] partFiles = target.listFiles(new FileFilterByPartFile());
// 对碎片数目进行判断
if (partFiles.length != (partcount - 1))
new RuntimeException("碎片个数错误, 不是" + (partcount - 1) + "个");
// 对碎片名的判断
for (int i = 0; i < (partcount - 1); i++) {
File file = new File(target, (i + 1) + ".part");
if (!file.exists()) {
throw new RuntimeException(file.getName() + "不存在");
}
}
// 合并
mergeFile(target, filename, partcount);
}
public class FilenameFilterBySuffix implements FilenameFilter {
public boolean accept(File file, String name) {
return name.endsWith(".properties");
}
}
public class FileFilterByPartFile implements FileFilter {
public boolean accept(File pathname) {
return pathname.getName().endsWith(".part");
}
}
③. 合并文件
/**
* 合并文件
*
* @param target
* 要合并文件的目录
* @param filename
* 文件名
* @param count
* 碎片数目
* @throws IOException
*/
private static void mergeFile(File target, String filename, int count)
throws IOException {
List<FileInputStream> streams = new ArrayList<FileInputStream>();
for (int i = 0; i < (count - 1); i++) {
streams.add(new FileInputStream(new File(target, (i + 1) + ".part")));
}
// 获取枚举接口对象
Enumeration<FileInputStream> enumeration = Collections
.enumeration(streams);
SequenceInputStream sequenceInputStream = new SequenceInputStream(
enumeration);
FileOutputStream fileOutputStream = new FileOutputStream(new File(
target, filename));
byte[] bs = new byte[1024];
int len = 0;
while ((len = sequenceInputStream.read(bs)) != -1) {
fileOutputStream.write(bs, 0, len);
}
fileOutputStream.close();
sequenceInputStream.close();
}
三、管道流
管道流的主要作用是可以进行两个线程间的通讯,分为管道输出流(PipedOutputStream)、管道输入流(PipedInputStream),如果想要进行管道输出,则必须把输出流连在输入流之上。
1. 管道流的常用方法
①. PipedOutputStream类
// 创建连接到指定管道输入流的管道输出流
public PipedOutputStream(PipedInputStream snk) throws IOException
// 将此管道输出流连接到接收者。如果此对象已经连接到其他某个管道输入流,则抛出 IOException。
public void connect(PipedInputStream snk) throws IOException
②. PipedInputStream类
// 创建 PipedInputStream,使其连接到管道输出流 src。写入 src 的数据字节可用作此流的输入。
public PipedInputStream(PipedOutputStream src) throws IOException
// 使此管道输入流连接到管道输出流 src。如果此对象已经连接到其他某个管道输出流,则抛出 IOException。
public void connect(PipedOutputStream src) throws IOException
2. 范例
public class Send implements Runnable {
private PipedOutputStream pipedOutputStream = null; // 声明管道输出流
public Send() {
pipedOutputStream = new PipedOutputStream(); // 实例化输出流
}
public void run() {
String str = "Hello World!!!";
try {
pipedOutputStream.write(str.getBytes());
pipedOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// 得到此线程的管道输出流
public PipedOutputStream getPipedOutputStream() {
return pipedOutputStream;
}
}
public class Receive implements Runnable{
private PipedInputStream pipedInputStream = null;
public Receive () {
pipedInputStream = new PipedInputStream();
}
public PipedInputStream getPipedInputStream() {
return pipedInputStream;
}
public void run() {
byte[] bytes = new byte[1024];
int len = 0;
try {
len = pipedInputStream.read(bytes);
pipedInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("接收到的内容:" + new String(bytes, 0, len));
}
}
public static void main(String[] args) {
Send send = new Send();
Receive receive = new Receive();
try {
send.getPipedOutputStream().connect(receive.getPipedInputStream()); // 链接管道
} catch (IOException e) {
e.printStackTrace();
}
new Thread(send).start();
new Thread(receive).start();
}
四、RandomAccessFile
RandomAccessFile类的主要功能是完成随机读取功能,可以读取指定位置的内容。
1. RandomAccessFile 类的常用操作方法
// 接收File类的对象,指定操作路径,但是设置时需要设置模式。“r”:只读、“w”:只写、“rw”:读写
public RandomAccessFile(File file, String mode) throws FileNotFoundException
// 不再使用File类对象表示文件,直接输入一个固定的文件路径
public RandomAccessFile(String name, String mode) throws FileNotFoundException
// 关闭操作
public void close() throws IOException
// 将内容读取到一个byte数据之中。
public int read(byte[] b) throws IOException
// 读取一个字节
public final byte readByte() throws IOException
// 读取整形数据
public final int readInt() throws IOException
// 设置都指针的位置
public void seek(long pos) throws IOException
// 将一个字符串写入文件之中,按字节的方式处理
public final void writeBytes(String s) throws IOException
// 将一个int数据写入文件,长度为4
public final void writeInt(int v) throws IOException
// 指针跳过多少个字节
public int skipBytes(int n) throws IOException
五、内存操作流(ByteArrayInputStream和ByteArrayOutputStream)
ByteArrayInputStream的主要完成将内容写入到内存之中,而ByteArrayOutputStream的功能主要是将内存中的数据输出。
范例:利用内存操作流完成一个大小写转换的程序
String str = "HELLO WORLD!";
OutputStream baos = null; // 内存输出流
InputStream bais = null; // 内存输入流
bais = new ByteArrayInputStream(str.getBytes()); // 向内村输出内容
baos = new ByteArrayOutputStream(); // 准备从内存ByteArrayInputStream读取数据
int temp = 0;
while ((temp = bais.read()) != -1) {
char c = (char) temp; // 读取的数字变为字符
baos.write(Character.toLowerCase(c)); // 将字符vain为小写
}
// 所有的数据全都在ByteArrayOutputStream中
String strs = baos.toString();
System.out.println(strs);
try {
baos.close();
bais.close();
} catch (Exception e) {
e.printStackTrace();
}