1.如何获取文件的属性信息?
boolean exists():判断文件或目录是否存在
String getName():返回文件或目录的名称
String getParent():返回父路径的路径名字符串
String getAbsolutePath():返回绝对路径的路径名字符串
String getPath():返回抽象路径的路径名字符串
boolean isAbsolute():判断当前路径是否为绝对路径
boolean isDirectory():判断当前文件是否为目录
boolean isFile():判断当前文件是否为一个标准文件
boolean isHidden():判断当前文件是否是一个隐藏文件
long lastModified():返回当前文件最后一次被修改的时间
long length():返回当前文件的长度
boolean canRead():判断是否可读
boolean canWrite():判断是否可写
有些属性是无法获取的,例如文件的创建时间。
2.如何判断文件是否为空?
在File类中没有提供直接的方法判断文件是否为空,可以借助length()返回值为0来判断
3.如何实现文件的创建、删除、移动?
创建:createNewFile()和createTempFile()
删除:delete()
移动:renameTo()
创建文件时应先检测文件是否存在,如果不存在就创建;如果目录错误,创建时也会发生异常。
4.如何创建和删除文件夹?
创建:mkdir()和mkdirs()
删除: delete(),如果不为空,需要遍历文件夹递归删除。
5.如何遍历目录中所有的文件?
public File[] listFiles()
因为目录中可能包含文件夹,所以需要借助listFiles()方法递归遍历目录中所有的文件。
注意与public String[] list()区分开来。
6.如何获取文件夹的大小?
long size=0;
public void getDirSize(File file){
if(file.isFile()){
size+=file.length();
}else if(file.isDirectory()){
File[] f1=file.listFiles();
for(int i=0;i<f1.length;i++){
getDirSize(f1[i]);
}
}
}
7.什么是流?如何分类?具体包含哪些类?
流代表经过管道流通的数据,为了进行数据的输入输出操作,Java把不同的输入输出源抽象表述为流。
按照流向分类,可以分为输入流和输出流。
按照处理单位不同,可以分为字节流和字符流。
字节流:
主要包含InputStream和OutputStream两个基础类。
1》FileInputStream/FileOutputStream(读写文件)
2》BufferedInputStream/BufferedOutputStream(读写缓冲流)
3》ByteArrayInputStream/ByteArrayOutputStream(按字节数组读写内存中临时数据)
4》DataInputStream/DataOutputStream(读写基本类型和String)
5》ObjectInputStream/ObjectOutputStream(读写对象)
6》PipedInputStream/PipedOutputStream(主要在线程中使用)
7》PrintStream(打印流,可以一次写一行)
8》RandomAccessFile(随机访问文件),继承Object,不属于InputStream和OutputStream的子类
字符流:
主要包含Reader和Writer两个基础类。
1》FileReader/FileWriter(只能采用系统默认编码方式读写)
2》InputStreamReader/OutputStreamWriter(转换流,采用指定编码方式读写)
3》BufferedReader/BufferedWriter(缓冲流,借助readLine()和newLine()可以一次读写一行)
4》CharArrayReader/CharArrayWriter(按字符数组读写)
5》PipedReader/PipedWriter(主要在线程中使用)
6》PrintWriter(打印流,可以一次写一行)
所有流对象的应用,都有共同步骤:
构建流对象;读写数据;释放资源,假如有多层流的嵌套,直接关闭外层流即可。
8.如何实现字节流和字符流之间的转化?
字节流和字符流转化时需要注意两个问题:一个字符等于两个字节;编码不一致。
InputStreamReader可完成字节流到字符流的转化。为了达到最高效率,可以使用BufferedReader包装。
OutputStreamWriter可完成字符流到字节流的转化。为了达到最高效率,可以使用BufferedWriter包装。
9.如何判断要读的文件是否到达末尾?
InputStream的read()方法返回-1表示到达末尾,Reader的read()方法返回-1表示到达末尾,BufferedReader的readLine()方法返回 null表示到达末尾。
10.如何读文件、写文件?
如果是字节流文件,例如图片、流媒体等,可以用如下方式获取。
public void testRead() throws Exception{
int temp=-1;
FileInputStream in=new FileInputStream("d:\\a.txt");
BufferedInputStream bs=new BufferedInputStream(in);
while((temp=bs.read())!=-1){
System.out.println((char)temp);
}
bs.close();
in.close();
如果是纯文本字符文件,例如txt,log,csv等格式,可以用如下方式获取。
public void testRead() throws Exception{
String temp=null;
FileReader in=new FileReader("d:\\a.txt");
BufferedReader br=new BufferedReader(in);
while((temp=br.readLine())!=null){
System.out.println(temp);
}
br.close();
in.close();
public void testWrite() throws Exception{
FileOutputStream fs=new FileOutputStream("d:\\a.txt");
BufferedOutputStream bs=new BufferedOutputStream(fs);
fs.write('a');
bs.close();
fs.close();
}
如果是纯文本字符文件,例如txt,log,csv等格式,可以用如下方式写入。
public void testWrite() throws Exception{
FileWriter fw=new FileWriter("d:\\a.txt");
BufferedWriter bw=new BufferedWriter(fw);
bw.write('a');
bw.close();
fw.close();
}
11.如何以追加方式写文件?
FileOutputStream和FileWriter都提供了相应的构造方法用来指定是否以追加方式写文件。
public FileOutputStream(File file,boolean append) throws FileNotFoundException;
public FileOutputStream(String fileName,boolean append) throws FileNotFoundException;
public FileWriter(File file,boolean append) throws IOException;
public FileWriter(String fileName,boolean append) throws IOException;
文件复制:
public void copyFile(String oldPath,String newPath){
InputStream in=null;
FileOutputStream fs==null;
try{
int byteread=0;
File oldFile=new File(oldPath);
if(oldFile.exists()){
in=new FileInputStream(oldPath);
fs=new FileOutputStream(newPath);
byte[] buffer=new byte[1024];
while((byteread=in.read(buffer))!=-1){
fs.write(buffer,0,byteread);
}
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(in!=null)
in.close();
if(fs!=null)
fs.close();
}
}
文件夹复制:
public void copyFolder(String oldPath,String newPath){
FileInputStream in=null;
FileOutputStream fs==null;
try{
(new File(newPath)).mkdirs();
int byteread=0;
File oldFile=new File(oldPath);
String[] nameArray=oldFile.list();
File temp=null;
for(int i=0;i<nameArray.length;i++){
if(oldPath.endsWith(File.separator)){
temp=new File(oldPath+nameArray[i]);
}else{
temp=new File(oldPath+File.separator+nameArray[i]);
}
}
if(temp.isFile()){
in=new FileInputStream(temp);
fs=new FileOutputStream(newPath+"/"+(temp.getName().toString()));
byte[] buffer=new byte[1024*5];
while((byteread=in.read(buffer))!=-1){
fs.write(buffer,0,byteread);
}
fs.flush();
}
if(temp.isDirectory()){
copyFolder(oldPath+"/"+nameArray[i],newPath+"/"+nameArray[i]);
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(in!=null)
in.close();
if(fs!=null)
fs.close();
}
}
13.如何在文件的任意位置进行读写?
利用RandomAccessFile可以实现任意位置读写,提供了两个构造方法:
public RandomAccessFile(File file,String mode) throws FileNotFoundException;
public RandomAccessFile(String fileName,String mode) throws FileNotFoundException;
其中mode有四种,“r”“rw”“rws”“rwd”,“rwd”可用于减少IO操作次数。
写操作:
public static void testWrite() throws Exception{
RandomAccessFile rf=new RandomAccessFile("c:\\a.txt","rw");
rf.seek(rf.length());//指定位置写入,以字节为单位
rf.writeByte('a');
rf.writeUTF("我");
rf.close();
}
读操作:
public static void testRead() throws Exception{
RandomAccessFile rf=new RandomAccessFile("c:\\a.txt","r");
rf.seek(0);//指定位置读取,以字节为单位
System.out.println((char)rf.read());
System.out.println(rf.readUTF());
rf.close();
}
14.使用缓冲流写文件时,为什么内容没有写入?
使用缓冲流写文件时,必须显示调用flush()和close()方法,否则无法将缓冲区中的信息输出到目标文件中。
注意:使用close()方法时,会默认执行flush()方法的功能,因此close()方法也可以将缓冲区中的信息输出到目标文件中。
15.如何实现文件的分割与合并?
使用RandomAccessFile类可以实现文件的分割与合并。
文件分割:
//fileName源文件,filterFolder分割文件所在目录,size每一份大小,以KB为单位
public void cut(String fileName,String filterFolder,int size) throws Exception{
size*=1024;
int maxx=0;
File outFolder=new File(filterFolder);
if(!outFolder.exists()){
outFolder.mkdirs();
}
File inFile=new File(fileName);
int fileLength=(int)inFile.length();
int value=fileLength/size;//要分割的个数
RandomAccessFile rf=new RandomAccessFile(inFile,"r");
int i=0;
int j=0;
//根据要分割的数目输出文件
for(;j<value;j++){
File outFile=new File(filterFolder+File.separator+inFile.getName()+j+"tmp");
RandomAccessFile outt=new RandomAccessFile(outFile,"rw");
maxx+=size;
for(;i<maxx;i++){
outt.write(rf.read());
}
outt.close();
}
File outFile=new File(filterFolder+File.separator+inFile.getName()+j+"tmp");
RandomAccessFile outt=new RandomAccessFile(outFile,"rw");
for(;i<fileLength;i++){
outt.write(rf.read());
}
outt.close();
rf.close();
}
文件合并:
//fileName合并之后的文件,filterFolder分割文件所在目录,filterName分割后的文件后缀
public void unit(String fileName,String filterFolder,final String filterName) throws Exception{
File[] tt;
File inFile=new File(filterFolder);//在当前目录下的文件
File outFile=new File(fileName);//输出的文件
RandomAccessFile outt=new RandomAccessFile(outFile,"rw");
//取得符合条件的文件名
tt=inFile.listFiles(new FilenameFilter(){
public boolean accept(File dir,String name){
String rr=new File(name).toString();
return rr.endsWith(filterName);
}
}
);
//将所有文件写入一个文件
for(int i=0;i<tt.length;i++){
RandomAccessFile inn=new RandomAccessFile(tt[i],"r");
int c;
while((c=inn.read())!=-1){
outt.write(c);
}
}
outt.close();
}
16.什么是NIO?与IO有什么区别和联系?
NIO与原有的IO有相同的作用和目的,是基于原有IO的扩展和改进。
NIO新特性:
1》更加灵活的可伸缩的IO接口,包括Channel的出现和新的多元的非阻塞的IO机制;
2》快速缓存的二进制和字符IO接口;
3》字符集的编码器和解码器;
4》基于Perl风格的正则表达式的模式匹配机制;
5》改良的文件系统接口,支持锁定和内存映射;
6》新的违例类能使得用户更加有针对性的处理IO错误;
7》增加了对并发的支持。
NIO并不是对IO的替代,虽然NIO在IO操作时速度快,但是其实现借助了大量的本地代码,对操作系统和硬件平台有很强的依赖性。
区别:
一.IO是面向流的,NIO是面向缓冲区的。
二.IO的各种流是阻塞的,NIO是非阻塞模式。
三.Java NIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:
这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。
17.如何使用NIO读写文件?
并不是所有的IO流类都支持NIO,支持NIO的有FileInputStream,FileOutputStream,RandomAccessFile.
读操作:
写操作:
文件复制:
18.什么是字符编码和解码?
在字符和字节信息相互转化时,需要涉及到编码和解码操作。
在NIO中提供了与字符集、编码、解码相关的API,如:
Charset:字符集,用于描述字符和字节之间的命名映射关系。
CharsetDecoder:解码器,用于实现将字节解码为字符。
CharsetEncoder:编码器,用于实现将字符编码为字节。
19.读写文件时为什么中文字符经常会产生乱码?
存储文件时,需要将文件中的字符转换为二进制字节信息,属于编码。读取文件时,需要将字节信息转换为字符信息,称为解码。
写文件和读文件使用不同的字符集时,就会产生乱码。另外API使用不当也会产生乱码,例如InputStream读取中文字符的文件,
InputStream是以字节为单位读取的,所以会将中文字符拆成两个字节分两次读取,这就是中文乱码而英文正常的原因。
20.如何解决FileReader读文件乱码的问题?
因为FileReader读文件只能采用系统默认编码,所以可能会存在字符集不一致问题。解决办法就是放弃FileReader采用 InputStreamReader,在读取时指定编码方式。
在读写文件时,DataInputStream和DataOutputStream必须成对使用,而且读写时必须采取对应的顺序和类型,否则会产生乱码。
有两种方式:一种是使用RandomAccessFile,还有一种是使用FileChannel。
1》new RandomAccessFile(file,"rws")中的"rws"代表以独占方式访问文件
2》FileChannel是NIO提供的一个类,该类提供了锁定的方法。
RandomAccessFile rf=new RandomAccessFile(new File("c:\\a.txt"),"rws");
FileChannel fc=rf.getChannel();
//尝试获取文件锁,如果被占用返回null
FileLock fl=fc.tryLock();
if(fl.isValid()){
//省略写入操作代码
fl.realease();//释放文件锁
}else{
//其他用户正在写入
}
23.如何实现对文件和字符串加密、解密?
常用的加密算法有DES、RSA、MD5、SHA-1。注意MD5和SHA-1算法只能加密不能解密,是不可逆的。
24.如何实现对文件和目录的压缩、解压缩?
java支持的压缩格式有zip、gzip、jar等,下面以zip举例:zip压缩可以使用ZipEntry类和ZipOutputStream类,zip解压缩可以使用ZipEntry类和ZipInputStream类。
可以使用Properties类读写properties文件,它使用的是ISO-8859-1编码,每个字节是一个Latin1字符,因此对于非Latin1字符在读写时就会发生乱码,需要先进行转换。为了避免读写中文字符乱码,需要先将字符进行转义。
可以使用DOM和SAX读写xml文件。
DOM可以实现对xml的读取、增加、修改、删除,但是在文件很大时比较耗费内存。
SAX是一边读取一边处理,对内存要求较低,但是仅支持文件读取。
27.如何读写xml中的元素属性?
对xml中元素属性的读写操作需要使用DOM技术实现。使用Element类的getAttributeNode()和getAttribute()方法可以获取属性信息,通过setAttributeNode()和setAttribute()方法可以设置属性信息。
读取xml中元素属性:
public void parseAttr(Element elt,String name){
//String val=elt.getAttributeName(name);//获取属性值
//System.out.println(val);
Attr attr=elt.getAttributeNode(name);//获取属性对象
if(attr!=null){
System.out.println(attr.getName()+"/"+attr.getValue());
}
}
设置xml中元素属性:
public void setAttr(Document doc,Element elt){
Attr attr=doc.createAttribute("年龄");
Text attrText=doc.createTextNode(68);
attr.appendChild(attrText);
elt.setAttributeNode(attr);
//elt.setAttribute(name,value);//设置属性值
}
28.如何读写csv格式文件?
csv文件与普通TXT文件不同的是,csv文件中的每项数据都是用逗号分隔,因此读写csv文件与读写txt文件相比只是多处理一些逗号和换行符而已。
写csv文件:
public static void main(String[] args){
try{
FileWriter fw=new FileWriter("c:\\a.csv");
fw.write("aa,bb,cc,dd,ee\r\n");
fw.write("aa1,bb1,cc1,dd1,ee1\r\n");
fw.close();
}catch(IOException e){
e.printStackTrace();
}
}
读csv文件:
public static void main(String[] args){
InputStreamReader fr=null;
BufferedReader br=null;
try{
fr=new InputStreamReader(new FileInputStream("d:\\a.csv"));
br=new BufferedReader(fr);
String rec=null;
String[] argsArr=null;
while((rec=br.readLine())!=null){
argsArr=rec.split(",");
for(int i=0;i<argsArr.length;i++){
System.out.println("num"+(i+1)+":"+argsArr[i]);
}
}
}catch(IOException e){
e.printStackTrace();
}finally{
try{
if(fr!=null)fr.close();
if(br!=null)br.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
注意:csv文件内容中的逗号为半角,不能为全角。
29.如何为图片文件生成缩略图?
在实现缩略图的过程中,主要使用BufferedImage和ImageIO两个类。首先将图片信息读取到BufferedImage对象中,接着构造缩略图的BufferedImage对象,最后将缩略图输出。ImageIO提供了read()和write()方法,用于读写图片中的信息。
示例代码:
public class Test{
//fromFileStr源图片路径,saveToFileStr缩略图路径,width:缩略图的宽,height:缩略图的高
public static void saveImageAsJpg(String fromFileStr,String saveToFileStr,int width,int height){
BufferedImage srcImage;
String imgType="JPEG";
if(fromFileStr.toLowerCase().endsWith(".png")){
imgType="PNG";
}
File saveFile=new File(saveToFileStr);
File fromFile=new File(fromFileStr);
srcImage=ImageIO.read(fromFile);
if(width>0||height>0){
srcImage=resize(srcImage,width,height);
}
ImageIO.write(srcImage,imgType,saveFile);
}
//将源图片的BufferedImage生成缩略图
public static BufferedImage resize(BufferedImage source,int targetW,int targetH){
int type=source.getType();
BufferedImage target=null;
double sx=(double)targetW/source.getWidth();
double sy=(double)targetH/source.getHeight();
//如果不需要等比缩放,将下面的if-else去掉即可
if(sx>sy){
sx=sy;
targetW=(int)(sx*source.getWidth());
}else{
sy=sx;
targetH=(int)(sy*source.getHeight());
}
if(type==BufferedImage.TYPE_CUSTOM){
ColorModel cm=source.getColorModel();
WritableRaster raster=cm.createCompatibleWritableRaster(targetW,targetH);
boolean alphaPremultiplied=cm.isAlphaPremultiplied();
target=new BufferedImage(cm,raster,alphaPremultiplied,null);
}else{
target=new BufferedImage(targetW,targetH,type);
}
Graphics2D g=target.createGraphics();
g.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g.drawRenderedImage(source,AffineTransform.getScaleInstance(sx,sy));
g.dispose();
return target;
}
public static void main(String[] args){
try{
Test.saveImageAsJpg("d:/a.gif","d:/me/b.gif",50,50);
}catch(Exception e){
e.printStackTrace();
}
}
}
30.如何读写Excel文件?
对于Excel文件操作需要借助第三方组件,如POI和JXL。
31.如何读写Word文件?
同样需要借助第三方组件才能操作,例如jacob、iText、POI和java2word。其中jacob是最常用的一个。
32.如何读写PDF文件?
同样需要借助第三方组件才能操作,例如pdfbox、xpdf、iText。
33.Java中的NIO,BIO,AIO分别是什么?
boolean exists():判断文件或目录是否存在
String getName():返回文件或目录的名称
String getParent():返回父路径的路径名字符串
String getAbsolutePath():返回绝对路径的路径名字符串
String getPath():返回抽象路径的路径名字符串
boolean isAbsolute():判断当前路径是否为绝对路径
boolean isDirectory():判断当前文件是否为目录
boolean isFile():判断当前文件是否为一个标准文件
boolean isHidden():判断当前文件是否是一个隐藏文件
long lastModified():返回当前文件最后一次被修改的时间
long length():返回当前文件的长度
boolean canRead():判断是否可读
boolean canWrite():判断是否可写
有些属性是无法获取的,例如文件的创建时间。
2.如何判断文件是否为空?
在File类中没有提供直接的方法判断文件是否为空,可以借助length()返回值为0来判断
3.如何实现文件的创建、删除、移动?
创建:createNewFile()和createTempFile()
删除:delete()
移动:renameTo()
创建文件时应先检测文件是否存在,如果不存在就创建;如果目录错误,创建时也会发生异常。
4.如何创建和删除文件夹?
创建:mkdir()和mkdirs()
删除: delete(),如果不为空,需要遍历文件夹递归删除。
5.如何遍历目录中所有的文件?
public File[] listFiles()
因为目录中可能包含文件夹,所以需要借助listFiles()方法递归遍历目录中所有的文件。
注意与public String[] list()区分开来。
6.如何获取文件夹的大小?
long size=0;
public void getDirSize(File file){
if(file.isFile()){
size+=file.length();
}else if(file.isDirectory()){
File[] f1=file.listFiles();
for(int i=0;i<f1.length;i++){
getDirSize(f1[i]);
}
}
}
7.什么是流?如何分类?具体包含哪些类?
流代表经过管道流通的数据,为了进行数据的输入输出操作,Java把不同的输入输出源抽象表述为流。
按照流向分类,可以分为输入流和输出流。
按照处理单位不同,可以分为字节流和字符流。
字节流:
主要包含InputStream和OutputStream两个基础类。
1》FileInputStream/FileOutputStream(读写文件)
2》BufferedInputStream/BufferedOutputStream(读写缓冲流)
3》ByteArrayInputStream/ByteArrayOutputStream(按字节数组读写内存中临时数据)
4》DataInputStream/DataOutputStream(读写基本类型和String)
5》ObjectInputStream/ObjectOutputStream(读写对象)
6》PipedInputStream/PipedOutputStream(主要在线程中使用)
7》PrintStream(打印流,可以一次写一行)
8》RandomAccessFile(随机访问文件),继承Object,不属于InputStream和OutputStream的子类
字符流:
主要包含Reader和Writer两个基础类。
1》FileReader/FileWriter(只能采用系统默认编码方式读写)
2》InputStreamReader/OutputStreamWriter(转换流,采用指定编码方式读写)
3》BufferedReader/BufferedWriter(缓冲流,借助readLine()和newLine()可以一次读写一行)
4》CharArrayReader/CharArrayWriter(按字符数组读写)
5》PipedReader/PipedWriter(主要在线程中使用)
6》PrintWriter(打印流,可以一次写一行)
所有流对象的应用,都有共同步骤:
构建流对象;读写数据;释放资源,假如有多层流的嵌套,直接关闭外层流即可。
8.如何实现字节流和字符流之间的转化?
字节流和字符流转化时需要注意两个问题:一个字符等于两个字节;编码不一致。
InputStreamReader可完成字节流到字符流的转化。为了达到最高效率,可以使用BufferedReader包装。
OutputStreamWriter可完成字符流到字节流的转化。为了达到最高效率,可以使用BufferedWriter包装。
9.如何判断要读的文件是否到达末尾?
InputStream的read()方法返回-1表示到达末尾,Reader的read()方法返回-1表示到达末尾,BufferedReader的readLine()方法返回 null表示到达末尾。
10.如何读文件、写文件?
如果是字节流文件,例如图片、流媒体等,可以用如下方式获取。
public void testRead() throws Exception{
int temp=-1;
FileInputStream in=new FileInputStream("d:\\a.txt");
BufferedInputStream bs=new BufferedInputStream(in);
while((temp=bs.read())!=-1){
System.out.println((char)temp);
}
bs.close();
in.close();
}
public void testRead() throws Exception{
String temp=null;
FileReader in=new FileReader("d:\\a.txt");
BufferedReader br=new BufferedReader(in);
while((temp=br.readLine())!=null){
System.out.println(temp);
}
br.close();
in.close();
}
public void testWrite() throws Exception{
FileOutputStream fs=new FileOutputStream("d:\\a.txt");
BufferedOutputStream bs=new BufferedOutputStream(fs);
fs.write('a');
bs.close();
fs.close();
}
如果是纯文本字符文件,例如txt,log,csv等格式,可以用如下方式写入。
public void testWrite() throws Exception{
FileWriter fw=new FileWriter("d:\\a.txt");
BufferedWriter bw=new BufferedWriter(fw);
bw.write('a');
bw.close();
fw.close();
}
11.如何以追加方式写文件?
FileOutputStream和FileWriter都提供了相应的构造方法用来指定是否以追加方式写文件。
public FileOutputStream(File file,boolean append) throws FileNotFoundException;
public FileOutputStream(String fileName,boolean append) throws FileNotFoundException;
public FileWriter(File file,boolean append) throws IOException;
public FileWriter(String fileName,boolean append) throws IOException;
文件复制:
public void copyFile(String oldPath,String newPath){
InputStream in=null;
FileOutputStream fs==null;
try{
int byteread=0;
File oldFile=new File(oldPath);
if(oldFile.exists()){
in=new FileInputStream(oldPath);
fs=new FileOutputStream(newPath);
byte[] buffer=new byte[1024];
while((byteread=in.read(buffer))!=-1){
fs.write(buffer,0,byteread);
}
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(in!=null)
in.close();
if(fs!=null)
fs.close();
}
}
文件夹复制:
public void copyFolder(String oldPath,String newPath){
FileInputStream in=null;
FileOutputStream fs==null;
try{
(new File(newPath)).mkdirs();
int byteread=0;
File oldFile=new File(oldPath);
String[] nameArray=oldFile.list();
File temp=null;
for(int i=0;i<nameArray.length;i++){
if(oldPath.endsWith(File.separator)){
temp=new File(oldPath+nameArray[i]);
}else{
temp=new File(oldPath+File.separator+nameArray[i]);
}
}
if(temp.isFile()){
in=new FileInputStream(temp);
fs=new FileOutputStream(newPath+"/"+(temp.getName().toString()));
byte[] buffer=new byte[1024*5];
while((byteread=in.read(buffer))!=-1){
fs.write(buffer,0,byteread);
}
fs.flush();
}
if(temp.isDirectory()){
copyFolder(oldPath+"/"+nameArray[i],newPath+"/"+nameArray[i]);
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(in!=null)
in.close();
if(fs!=null)
fs.close();
}
}
13.如何在文件的任意位置进行读写?
利用RandomAccessFile可以实现任意位置读写,提供了两个构造方法:
public RandomAccessFile(File file,String mode) throws FileNotFoundException;
public RandomAccessFile(String fileName,String mode) throws FileNotFoundException;
其中mode有四种,“r”“rw”“rws”“rwd”,“rwd”可用于减少IO操作次数。
写操作:
public static void testWrite() throws Exception{
RandomAccessFile rf=new RandomAccessFile("c:\\a.txt","rw");
rf.seek(rf.length());//指定位置写入,以字节为单位
rf.writeByte('a');
rf.writeUTF("我");
rf.close();
}
读操作:
public static void testRead() throws Exception{
RandomAccessFile rf=new RandomAccessFile("c:\\a.txt","r");
rf.seek(0);//指定位置读取,以字节为单位
System.out.println((char)rf.read());
System.out.println(rf.readUTF());
rf.close();
}
14.使用缓冲流写文件时,为什么内容没有写入?
使用缓冲流写文件时,必须显示调用flush()和close()方法,否则无法将缓冲区中的信息输出到目标文件中。
注意:使用close()方法时,会默认执行flush()方法的功能,因此close()方法也可以将缓冲区中的信息输出到目标文件中。
15.如何实现文件的分割与合并?
使用RandomAccessFile类可以实现文件的分割与合并。
文件分割:
//fileName源文件,filterFolder分割文件所在目录,size每一份大小,以KB为单位
public void cut(String fileName,String filterFolder,int size) throws Exception{
size*=1024;
int maxx=0;
File outFolder=new File(filterFolder);
if(!outFolder.exists()){
outFolder.mkdirs();
}
File inFile=new File(fileName);
int fileLength=(int)inFile.length();
int value=fileLength/size;//要分割的个数
RandomAccessFile rf=new RandomAccessFile(inFile,"r");
int i=0;
int j=0;
//根据要分割的数目输出文件
for(;j<value;j++){
File outFile=new File(filterFolder+File.separator+inFile.getName()+j+"tmp");
RandomAccessFile outt=new RandomAccessFile(outFile,"rw");
maxx+=size;
for(;i<maxx;i++){
outt.write(rf.read());
}
outt.close();
}
File outFile=new File(filterFolder+File.separator+inFile.getName()+j+"tmp");
RandomAccessFile outt=new RandomAccessFile(outFile,"rw");
for(;i<fileLength;i++){
outt.write(rf.read());
}
outt.close();
rf.close();
}
文件合并:
//fileName合并之后的文件,filterFolder分割文件所在目录,filterName分割后的文件后缀
public void unit(String fileName,String filterFolder,final String filterName) throws Exception{
File[] tt;
File inFile=new File(filterFolder);//在当前目录下的文件
File outFile=new File(fileName);//输出的文件
RandomAccessFile outt=new RandomAccessFile(outFile,"rw");
//取得符合条件的文件名
tt=inFile.listFiles(new FilenameFilter(){
public boolean accept(File dir,String name){
String rr=new File(name).toString();
return rr.endsWith(filterName);
}
}
);
//将所有文件写入一个文件
for(int i=0;i<tt.length;i++){
RandomAccessFile inn=new RandomAccessFile(tt[i],"r");
int c;
while((c=inn.read())!=-1){
outt.write(c);
}
}
outt.close();
}
16.什么是NIO?与IO有什么区别和联系?
NIO与原有的IO有相同的作用和目的,是基于原有IO的扩展和改进。
NIO新特性:
1》更加灵活的可伸缩的IO接口,包括Channel的出现和新的多元的非阻塞的IO机制;
2》快速缓存的二进制和字符IO接口;
3》字符集的编码器和解码器;
4》基于Perl风格的正则表达式的模式匹配机制;
5》改良的文件系统接口,支持锁定和内存映射;
6》新的违例类能使得用户更加有针对性的处理IO错误;
7》增加了对并发的支持。
NIO并不是对IO的替代,虽然NIO在IO操作时速度快,但是其实现借助了大量的本地代码,对操作系统和硬件平台有很强的依赖性。
区别:
一.IO是面向流的,NIO是面向缓冲区的。
二.IO的各种流是阻塞的,NIO是非阻塞模式。
三.Java NIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:
这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。
17.如何使用NIO读写文件?
并不是所有的IO流类都支持NIO,支持NIO的有FileInputStream,FileOutputStream,RandomAccessFile.
读操作:
写操作:
文件复制:
18.什么是字符编码和解码?
在字符和字节信息相互转化时,需要涉及到编码和解码操作。
在NIO中提供了与字符集、编码、解码相关的API,如:
Charset:字符集,用于描述字符和字节之间的命名映射关系。
CharsetDecoder:解码器,用于实现将字节解码为字符。
CharsetEncoder:编码器,用于实现将字符编码为字节。
19.读写文件时为什么中文字符经常会产生乱码?
存储文件时,需要将文件中的字符转换为二进制字节信息,属于编码。读取文件时,需要将字节信息转换为字符信息,称为解码。
写文件和读文件使用不同的字符集时,就会产生乱码。另外API使用不当也会产生乱码,例如InputStream读取中文字符的文件,
InputStream是以字节为单位读取的,所以会将中文字符拆成两个字节分两次读取,这就是中文乱码而英文正常的原因。
20.如何解决FileReader读文件乱码的问题?
因为FileReader读文件只能采用系统默认编码,所以可能会存在字符集不一致问题。解决办法就是放弃FileReader采用 InputStreamReader,在读取时指定编码方式。
在读写文件时,DataInputStream和DataOutputStream必须成对使用,而且读写时必须采取对应的顺序和类型,否则会产生乱码。
有两种方式:一种是使用RandomAccessFile,还有一种是使用FileChannel。
1》new RandomAccessFile(file,"rws")中的"rws"代表以独占方式访问文件
2》FileChannel是NIO提供的一个类,该类提供了锁定的方法。
RandomAccessFile rf=new RandomAccessFile(new File("c:\\a.txt"),"rws");
FileChannel fc=rf.getChannel();
//尝试获取文件锁,如果被占用返回null
FileLock fl=fc.tryLock();
if(fl.isValid()){
//省略写入操作代码
fl.realease();//释放文件锁
}else{
//其他用户正在写入
}
23.如何实现对文件和字符串加密、解密?
常用的加密算法有DES、RSA、MD5、SHA-1。注意MD5和SHA-1算法只能加密不能解密,是不可逆的。
24.如何实现对文件和目录的压缩、解压缩?
java支持的压缩格式有zip、gzip、jar等,下面以zip举例:zip压缩可以使用ZipEntry类和ZipOutputStream类,zip解压缩可以使用ZipEntry类和ZipInputStream类。
可以使用Properties类读写properties文件,它使用的是ISO-8859-1编码,每个字节是一个Latin1字符,因此对于非Latin1字符在读写时就会发生乱码,需要先进行转换。为了避免读写中文字符乱码,需要先将字符进行转义。
可以使用DOM和SAX读写xml文件。
DOM可以实现对xml的读取、增加、修改、删除,但是在文件很大时比较耗费内存。
SAX是一边读取一边处理,对内存要求较低,但是仅支持文件读取。
27.如何读写xml中的元素属性?
对xml中元素属性的读写操作需要使用DOM技术实现。使用Element类的getAttributeNode()和getAttribute()方法可以获取属性信息,通过setAttributeNode()和setAttribute()方法可以设置属性信息。
读取xml中元素属性:
public void parseAttr(Element elt,String name){
//String val=elt.getAttributeName(name);//获取属性值
//System.out.println(val);
Attr attr=elt.getAttributeNode(name);//获取属性对象
if(attr!=null){
System.out.println(attr.getName()+"/"+attr.getValue());
}
}
设置xml中元素属性:
public void setAttr(Document doc,Element elt){
Attr attr=doc.createAttribute("年龄");
Text attrText=doc.createTextNode(68);
attr.appendChild(attrText);
elt.setAttributeNode(attr);
//elt.setAttribute(name,value);//设置属性值
}
28.如何读写csv格式文件?
csv文件与普通TXT文件不同的是,csv文件中的每项数据都是用逗号分隔,因此读写csv文件与读写txt文件相比只是多处理一些逗号和换行符而已。
写csv文件:
public static void main(String[] args){
try{
FileWriter fw=new FileWriter("c:\\a.csv");
fw.write("aa,bb,cc,dd,ee\r\n");
fw.write("aa1,bb1,cc1,dd1,ee1\r\n");
fw.close();
}catch(IOException e){
e.printStackTrace();
}
}
读csv文件:
public static void main(String[] args){
InputStreamReader fr=null;
BufferedReader br=null;
try{
fr=new InputStreamReader(new FileInputStream("d:\\a.csv"));
br=new BufferedReader(fr);
String rec=null;
String[] argsArr=null;
while((rec=br.readLine())!=null){
argsArr=rec.split(",");
for(int i=0;i<argsArr.length;i++){
System.out.println("num"+(i+1)+":"+argsArr[i]);
}
}
}catch(IOException e){
e.printStackTrace();
}finally{
try{
if(fr!=null)fr.close();
if(br!=null)br.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
注意:csv文件内容中的逗号为半角,不能为全角。
29.如何为图片文件生成缩略图?
在实现缩略图的过程中,主要使用BufferedImage和ImageIO两个类。首先将图片信息读取到BufferedImage对象中,接着构造缩略图的BufferedImage对象,最后将缩略图输出。ImageIO提供了read()和write()方法,用于读写图片中的信息。
示例代码:
public class Test{
//fromFileStr源图片路径,saveToFileStr缩略图路径,width:缩略图的宽,height:缩略图的高
public static void saveImageAsJpg(String fromFileStr,String saveToFileStr,int width,int height){
BufferedImage srcImage;
String imgType="JPEG";
if(fromFileStr.toLowerCase().endsWith(".png")){
imgType="PNG";
}
File saveFile=new File(saveToFileStr);
File fromFile=new File(fromFileStr);
srcImage=ImageIO.read(fromFile);
if(width>0||height>0){
srcImage=resize(srcImage,width,height);
}
ImageIO.write(srcImage,imgType,saveFile);
}
//将源图片的BufferedImage生成缩略图
public static BufferedImage resize(BufferedImage source,int targetW,int targetH){
int type=source.getType();
BufferedImage target=null;
double sx=(double)targetW/source.getWidth();
double sy=(double)targetH/source.getHeight();
//如果不需要等比缩放,将下面的if-else去掉即可
if(sx>sy){
sx=sy;
targetW=(int)(sx*source.getWidth());
}else{
sy=sx;
targetH=(int)(sy*source.getHeight());
}
if(type==BufferedImage.TYPE_CUSTOM){
ColorModel cm=source.getColorModel();
WritableRaster raster=cm.createCompatibleWritableRaster(targetW,targetH);
boolean alphaPremultiplied=cm.isAlphaPremultiplied();
target=new BufferedImage(cm,raster,alphaPremultiplied,null);
}else{
target=new BufferedImage(targetW,targetH,type);
}
Graphics2D g=target.createGraphics();
g.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g.drawRenderedImage(source,AffineTransform.getScaleInstance(sx,sy));
g.dispose();
return target;
}
public static void main(String[] args){
try{
Test.saveImageAsJpg("d:/a.gif","d:/me/b.gif",50,50);
}catch(Exception e){
e.printStackTrace();
}
}
}
30.如何读写Excel文件?
对于Excel文件操作需要借助第三方组件,如POI和JXL。
31.如何读写Word文件?
同样需要借助第三方组件才能操作,例如jacob、iText、POI和java2word。其中jacob是最常用的一个。
32.如何读写PDF文件?
同样需要借助第三方组件才能操作,例如pdfbox、xpdf、iText。
33.Java中的NIO,BIO,AIO分别是什么?
NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
AIO:异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。