Java IO 流操作及多线程
• JAVA流的概念
• 字符输入输出流
• 字节输入输出流
• JAVA中文件与目录管理
• 线程基本概念
• 线程同步
• 线程死锁
• 线程挂起、恢复与终止
1 、Java 流的概念
流(Stream)是指在计算机的输入输出操作中各部件之间的数据流动。按照数据的
传输方向,流可分为输入流与输出流。Java语言里的流序列中的数据既可以是未经加
工的原始二进制数据,也可以是经过一定编码处理后符合某种特定格式的数据。
为了方便流的处理,Java语言提供了java.io包,在该包中的每一个类都代表了一种
特定的输入或输出流。为了使用这些流类,编程时需要引入这个包。
Java提供了两种
类型的输入输出流:一种是面向字节的流,数据的处理以字节为基本单位;另一种是
面向字符的流,用于字符数据的处理。字节流(Byte
Stream)每次读写8位二进制数,
也称为二进制字节流或位流。字符流一次读写16位二进制数,并将其做一个字符而不
是二进制位来处理。需要注意的是,为满足字符的国际化表示,Java语言的字符编码
采用的是16位的Unicode码,而普通文本文件中采用的是8位ASC码。
JavaIO 流操作
2 、输入输出流
在Java中,把不同类型的输入输出源抽象为流,其中输入和输出的数据称为数据流
(Data
Stream)。数据流是Java程序发送和接收数据的一个通道,数据流中包括输入
流(Input Stream)和输出流(Output
Stream)。
JavaIO 流操作
java.io包内容
3 、字符的输入流和输出流
字符流是针对字符数据的特点进行过优化的,因而提供一些面向字符的有用特性,
字符流的源或目标通常是文本文件。
Reader和Writer是java.io包中所有字符流的父类
由于它们都是抽象类,所以应使用它们的子类来创建实体对象,利用对象来处理相关
的读写操作。Reader和Writer的子类又可以分为两大类:一类用来从数据源读入数据
或往目的地写出数据(称为节点流),另一类对数据执行某种处理(称为处理流)
面向字符的输入流类都是Reader的子类,其类层次结构如图:
Reader 的主要子类及说明:
类名 功能描述
CharArrayReader 从字符数组读取的输入流
BufferedReader 缓冲输入字符流
PipedReader 输入管道
InputStreamReader 将字节转换到字符的输入流
FilterReader 过滤输入流
StringReader 从字符串读取的输入流
LineNumberReader 为输入数据附加行号
PushbackReader
返回一个字符并把此字节放回输入流
FileReader 从文件读取的输入流
Reader
所提供的方法,可以利用这些方法来获得流内的位数据:
方法 功能描述
void close() 关闭输入流
void mark() 标记输入流的当前位置
boolean markSupported() 测试输入流是否支持
mark
int read() 从输入流中读取一个字符
int read(char[] ch)
从输入流中读取字符数组
int read(char[] ch, int off, int
len) 从输入流中读 len 长的字符到 ch 内
boolean ready() 测试流是否可以读取
void reset() 重定位输入流
long skip(long n) 跳过流内的 n 个字符
使用 BufferedReader 类读取文件:
BufferedReader 类是用来读取缓冲区中的数据。使用时必须创建
FileReader 类
对象,再以该对象为参数创建 BufferedReader
类的对象。BufferedReader 类有两
个构造方法,其格式为:
public BufferedReader(Reader in);
//创建缓冲区字符输入流
public BufferedReader(Reader in,int
size); //创建输入流并设置缓冲区大小
面向字符的输出流
面向字符的输出流都是类 Writer
的子类,其类层次结构如图
面向字符的输出流
Writer 的主要子类及说明:
类名 功能说明
CharArrayWriter 写到字符数组的输出流
BufferedWriter 缓冲输出字符流
PipedWriter 输出管道
OutputStreamWriter 转换字符到字节的输出流
FilterWriter 过滤输出流
StringWriter 输出到字符串的输出流
PrintWriter 包含 print()和
println()的输出流
FileWriter 输出到文件的输出流
面向字符的输出流
Writer 所提供的方法如表:
方法 功能描述
void close() 关闭输出流
void flush() 将缓冲区中的数据写到文件中
void writer(int c) 将单一字符 c
输出到流中
void writer(String str) 将字符串 str
输出到流中
void writer(char[] ch) 将字符数组 ch
输出到流
void writer(char[] ch, int offset,
int
length)
将一个数组内自 offset 起到 length 长的字符输
出到流
面向字符的输出流
使用 BufferedWriter 类写入文件
BufferedWriter 类是用来将数据写入到缓冲区。使用时必须创建
FileWriter 类对象
再以该对象为参数创建 BufferedWriter 类的对象,最后需要用
flush()方法将缓冲区
清空。BufferedWriter类有两个构造方法,其格式为:
public BufferedWriter(Writer out);
//创建缓冲区字符输出流
public BufferedWriter(Writer out,int
size); //创建输出流并设置缓冲区大小
详细代码如备注
ps:
需要注意的是,调用 out 对象的
write()方法写入数据时,不会写入回车,因此需要
使用newLine()方法在每行数据后加入回车,以保证目标文件与源文件相一致。
字符流读取文件(一)
public static void
readFileByChars(String fileName) {
File file = new
File(fileName);
Reader reader = null;
try {
// 一次读一个字符
reader = new InputStreamReader( new
FileInputStream(file));
int tempchar;
while ((tempchar = reader.read()) !=
-1) {
//
对于windows下,\r\n这两个字符在一起时,表示一个换行。
// 但如果这两个字符分开显示时,会换两次行。
//
因此,屏蔽掉\r,或者屏蔽\n。否则,将会多出很多空行。
if ((( char) tempchar) != '\r')
{
System. out .print(( char)
tempchar);
}
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
字符流读取文件(二)
public static void
readFileByChars(String fileName) {
File file = new
File(fileName);
Reader reader = null;
try {
System. out
.println("以字符为单位读取文件内容,一次读多个字节:");
// 一次读多个字符
char[] tempchars = new
char[30];
int charread = 0;
reader = new InputStreamReader( new
FileInputStream(fileName));
//
读入多个字符到字符数组中,charread为一次读取字符数
while ((charread =
reader.read(tempchars)) != -1) {
// 同样屏蔽掉\r不显示
if ((charread ==
tempchars.length)&& (tempchars[tempchars.length - 1] !=
'\r')) {
System. out .print(tempchars);
} else {
for ( int i = 0; i < charread;
i++) {
if (tempchars[i] == '\r') {
continue;
} else {
System. out
.print(tempchars[i]);
}
}
}
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
}
}
}
Java 中面向字节的输入输出流和输出流
面向字节的输入输:
字节流以字节为传输单位,用来读写8位的数据,除了能够处理纯文本文件之外,
还能用来处理二进制文件的数据。
InputStream类和OutputStream类是所有字节流
的父类。
InputStream 类
面向字节的输入流都是InputStream类的子类,其类层次结构如图:
InputStream 的主要子类及说明:
类名 功能描述
FileInputStream 从文件中读取的输入流
PipedInputStream 输入管道
FilterInputStream 过滤输入流
ByteArrayInputStream
从字节数组读取的输入流
SequenceInputStream
两个或多个输入流的联合输入流,按顺序读取
ObjectInputStream 对象的输入流
LineNumberInputStream
为文本文件输入流附加行号
DataInputStream 包含读取 Java
标准数据类型方法的输入流
BufferedInputStream 缓冲输入流
PushbackInputStream
返回一个字节并把此字节放回输入流
面向字节的输入输
InputStream
流类中包含一套所有输入都需要的方法,可以完成最基本的从输入流
读入数据的功能
流类中包含一套所有输入都需要的方法,可以完成最基本的从输入流
读入数据的功能
面向字节的输入输
方法 功能描述
void close() 关闭输入流
void mark() 标记输入流的当前位置
void reset() 将读取位置返回到标记处
int read()
从输入流中当前位置读入一个字节的二进制数据,以此数据为低位字节,补足16
位的整型量(0~255)后返回,若输入流中当前位置没有数据,则返回-1
int read(byte
b[])
从输入流中的当前位置连续读入多个字节保存在数组中,并返回所读取的字节数
int read(byte
b[], int off, int
len)
从输入流中当前位置连续读len长的字节,从数组第off+1个元素位置处开始存放,
并返回所读取的字节数
int available() 返回输入流中可以读取的字节数
long skip(long n) 略过n个字节
long skip(long n) 跳过流内的n个字符
boolean
markSupported
()
测试输入数据流是否支持标记
面向字节的输出流
面向字节的输出流都是OutputStream类的子类,其类层次结构如图
面向字节的输出流
OutputStream 的主要子类及说明
面向字节的输出流
类名 功能描述
FileOutputStream 写入文件的输出流
PipedOutputStream 输出管道
FilterOutputStream 过滤输出流
ByteArrayOutputStream
写入字节数组的输出流
ObjectOutputStream 对象的输出流
DataOutputStream
包含写Java标准数据类型方法的输出流
BufferedOutputStream 缓冲输出流
PrintStream
包含print()和println()的输出流
OutputStream流类中包含一套所有输出都需要的方法,可以完成最基本的向输
出流写入数据的功能
流类中包含一套所有输出都需要的方法,可以完成最基本的向输
出流写入数据的功能
面向字节的输出流
方法 功能描述
void close() 关闭输出流
void flush() 强制清空缓冲区并执行向外设输出数据
void write(int b)
将参数b的低位字节写入到输出流
void write(byte b[])
按顺序将数组b[]中的全部字节写入到输出流
void write(byte b[], int off,
int len)
按顺序将数组b[]中第off+1个元素开始的len个数据
写入到输出流
由于InputStream和OutputStream都是抽象类,所以在程序中创建的输入流对象一般
是它们某个子类的对象,通过调用对象继承的read()和write()方法就可实现对相应外
设的输入输出操作
字节流读取文件代码演示(一)
public static void
readFileByBytes(String fileName) {
File file = new
File(fileName);
InputStream in = null;
try {
// 一次读一个字节
in = new
FileInputStream(file);
int tempbyte;
while ((tempbyte = in.read()) != -1)
{
System. out .write(tempbyte);
}
in.close();
} catch (IOException e) {
e.printStackTrace();
return;
}
}
字节流读取文件代码演示
(二)
public static void
readFileByBytes(String fileName) {
File file = new
File(fileName);
InputStream in = null;
try {
System. out
.println("以字节为单位读取文件内容,一次读多个字节:");
// 一次读多个字节
byte[] tempbytes = new
byte[100];
int byteread = 0;
in = new
FileInputStream(fileName);
ReadFromFile. showAvailableBytes
(in);
//
读入多个字节到字节数组中,byteread为一次读入的字节数
while ((byteread =
in.read(tempbytes)) != -1) {
System. out .write(tempbytes, 0,
byteread);
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e1) {
}
}
}
}
写入文件代码演示(一)
public class WriteFile
{
public static void main(String[]
args) {
FileOutputStream liu = null;
String name ="DavySun";
//流对象name
try {
liu = new
FileOutputStream("C:/Users/Administrator/Desktop/word.txt", true);
//创建流对象
byte[] b1 = name.getBytes();
//转换为byte数组
liu.write(b1); //写入
}
catch (FileNotFoundException
e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try{
liu.close();
}
catch(Exception e){}
}
写入文件代码演示(二)
public class WriteFile
{
public static void main(String[]
args) {
String name ="DavySun";
//流对象name
try {
//打开一个写文件器,构造函数中的第二个参数true
表示以追加形式写文件
FileWriter writer = new
FileWriter("C:/Users/Administrator/Desktop/word.txt", true);
writer.write(name);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Java 中文件输入输出流
文件输入输出流 FileInputStream 和
FileOutputStream 负责完成对本地磁盘文件
的顺序输入输出操作。
例子:
通过程序创建一个文件,从键盘输入字符,当遇到字符“#”时结束,在屏幕上显示该
文件的所有内容(详细请看备注例子)
文件输入输出流
Java 中文件与目录管理
目录是管理文件的特殊机制,同类文件保存在同一个目录下不仅可以简化文件
管理,而且还可以提高工作效率。Java 语言在 java.io
包中定义了一个 File 类专门
用来管理磁盘文件和目录
每个 File
类对象表示一个磁盘文件或目录,其对象属性中包含了文件或目录的
相关信息。通过调用 File
类提供的各种方法,能够创建、删除、重名名文件、判断
文件的读写权限以及是否存在,设置和查询文件的最近修改时间等。不同操作系统
具有不同的文件系统组织方式,通过使用 File 类对象,Java
程序可以用与平台无关
的、统一的方式来处理文件和目录。
创建 File 类对象需要给出其所对应的文件名或目录名,File
类的构造方法如表:
文件
构造方法 功能描述
public File(String path) 指定与 File
对象关联的文件或目录名,path 可以包含路径
及文件和目录名
public File(String path,
String name)
以 path 为路径,以 name 为文件或目录名创建 File
对象
public File(File dir, String
name)
用现有的 File 对象 dir 作为目录,以 name
作为文件或目录
名创建 File 对象
public File(UR ui)
使用给定的统一资源定位符来定位文件
新建文件代码演示
public class CreatFile
{
public static void main(String[]
args)
{
//新建文件
String fileName =
"C:/Users/Administrator/Desktop/Result.txt";
File myFilePath = new
File(fileName);
try
{
if (!myFilePath.exists())
{
myFilePath.createNewFile();
}
else
{
System. out .println("文件已存在");
}
}
catch (Exception e)
{
System. out
.println("新建文件操作出错");
e.printStackTrace();
}
}
}
删除文件代码演示
public class DeleteFile
{
public static void main(String[]
args)
{
//新建文件
String fileName =
"C:/Users/Administrator/Desktop/Result.txt";
File myFilePath = new
File(fileName);
try
{
if (myFilePath.exists())
{
myFilePath.delete();
}
else
{
System. out .println("文件不存在");
}
}
catch (Exception e)
{
System. out
.println("新建文件操作出错");
e.printStackTrace();
}
}
}
新建文件目录代码演示
public class CreatDir
{
public static void main(String[]
args)
{
//新建目录
String fileName =
"C:/Users/Administrator/Desktop/mine";
File myFolderPath = new
File(fileName);
try {
if (!myFolderPath.exists())
{
myFolderPath.mkdir();
}
else
{
System. out
.println("目录已经存在");
}
}
catch (Exception e) {
System. out
.println("新建目录操作出错");
e.printStackTrace();
}
}
}
java 多线程 编程基础
线程概念
多线程程序包含两条或两条以上并发运行的部分。程序中每个这样的部分都叫一
个线程(thread),每个线程都有独立的执行路径。
你一定知道多任务处理,因为它实际上被所有的现代操作系统所支持。然而,多
任务处理有两种截然不同的类型:基于进程的和基于线程的。认识两者的不同是十
分重要的。
对很多读者,基于进程的多任务处理是更熟悉的形式。进程(process)本质上是一个
执行的程序。因此,基于进程(process-based)
的多任务处理的特点是允许你的计算
机同时运行两个或更多的程序。举例来说,基于进程的多任务处理使你在运用文本
编辑器的时候可以同时运行Java编译器。在基于进程的多任务处理中,程序是调度
程序所分派的最小代码单位。
在基于线程(thread-based)
的多任务处理环境中,线程是最小的执行单位。这意味着
一个程序可以同时执行两个或者多个任务的功能。例如,一个文本编辑器可以在打
印的同时格式化文本。所以,多进程程序处理“大图片”,而多线程程序处理细节
问题
java 多线程 编程基础
线程模型
单线程环境,当一个线程因为等待资源时阻塞(block,挂起执行),整个程序
停止运行。
Java多线程的优点在于取消了主循环/轮询机制。一个线程可以暂停而不影响程序
的其他部分。例如,当一个线程从网络读取数据或等待用户输入时产生的空闲时间
可以被利用到其他地方。多线程允许活的循环在每一帧间隙中沉睡一秒而不暂停整
个系统。在Java程序中出现线程阻塞,仅有一个线程暂停,其他线程继续运行。
实现线程的两种方式:
1,继承Thread 类
2,实现Runnable 接口
方法 意义
getName 获得线程名称
getPriority 获得线程优先级
jsAlive 判定线程是否仍在运行
join 等待一个线程终止
run 线程的入口点.
sleep 在一段时间内挂起线程
start 通过调用运行方法来启动线程
线程管理方法
创建线程
2-1 :实现Runnable接口(代码如下备注一)
在NewThread
构造函数中,新的Thread对象由下面的语句创建:
Thread t = new Thread(this, "Demo
Thread");
2-2 :继承Thread实现创建线程(代码如下备注二)
当一个类继承Thread时,它必须重载run()方法,这个run()方法是新线程
的入口。它也必须调用start()方法去启动新线程执行。
子线程是由实例化NewThread对象
生成的,该对象从Thread类派生。注意NewThread
中super()的调用。该方
法调用了下列形式的Thread构造函数:
public Thread(String
threadName)这里,threadName指定线程名称。
java 多线程 编程基础
创建多线程
大于2个以上的线程使用被称之为多线程编程。详细请看备注代码
多线程是为了更有效率的让程序完成指定的效果
java 多线程 编程基础
线程同步
当两个或两个以上的线程需要共享资源,它们需要某种方法来确定资源在某一
刻仅被一个线程占用。达到此目的的过程叫做同步(synchronization)。
线程同步技术关键字synchronized,语句形式为:
synchronized(object) {
// statements to be
synchronized
}
其中,object是被同步对象的引用。详细请看备注