FKJAVA读书笔记--第十五章--输入/输出(修改)

使用输入机制,允许用户读取来自外部的数据、用户输入的数据;
使用输出机制,允许用户输入数据到存储设备中

1 理解IO流

java允许把不同的输入/输出源(键盘,文件,网络等)抽象表述为“流”Stream

通过流的方式,允许java程序使用相同的方式来访问不同的输入/输出源。

Stream是从起源(source)到接收(sink)的有序数据。

1.1 抽象成水管和水滴模型帮助理解


2 File类

File可以新建、删除、重命名文件和目录,File不能访问文件内容本身,访问文件内容本身需要使用输入/输出流

2.1 方法

2.1.1 访问文件名相关的方法

String getName()

String getPath()

File getAbsoluteFile() 

String getAbsolutePath()

String getParent() 返回此抽象路径名的父路径名的路径名字符串,如果此路径名没有指定父目录,则返回 null。如果是相对路径则获取不到父路径但可以通过:file.getAbsoluteFile().getParent()来间接的获取到父路径

boolean renameTo(File filename)

2.1.2 文件检测相关的方法
boolean exists()
boolean canRead()
booean canWrite()
boolean isFile()判断是否是文件,而不是目录
boolean isDirectory()
boolean isAbsoulte()

2.1.3 获取常规文件信息
long lastModified()返回文件最后修改的时间
long length()返回文件内容的长度

2.1.4 文件操作相关方法
boolean createNewFile()
boolean delete()
static File createTempFile(String prefix, String suffix): static方法
static File createTempFile(String prefix, String suffix, File directory) :static方法
void deleteOnExit()在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。

2.1.5 目录操作相关方法
boolean mkdir() 创建此抽象路径名指定的目录。
File file=new File(“c\bis”);
System.out.println(file.mkdir());这样就执行不了
boolean mkdirs()创建目录和其必要但不存在的父目录
int compareTo(File pathname) 按字母顺序比较两个抽象路径名。
boolen mkdirs()创建此抽象路径名指定的目录,包括创建必需但不存在的父目录。
File file=new File(“c\bis”);
System.out.println(file.mkdirs());可以创建
String[] list()列出File对象的所有子文件名和路径名,返回String数组
File[] listFiles()列出File对象的所有子文件和路径,返回String数组
static File[] listRoots()列出系统所有的根路径
File[] list = File.listRoots();
for (File file : list) {
System.out.println(file);
}

2.2 文件过滤器

//FilenameFilter中有一个accept方法,会对指定file的所有子目录或者文件进行迭代,满足要求的会被list()方法列出来

public class GetUserDir
{
    public static void main(String[] args) throws Exception
    {
        File file = new File("src/com/gu/test");
        String[] nameList = file.list(new MyFileNameFilter());//典型的command模式(命令模式):传入的MyFileNameFilter对象,就是为了传入accept方法体,该方法指定了哪些文件可以被列出
       for(String string : nameList)
        {
            System.out.println(string);
        }
    }

} 

class MyFileNameFilter implements FilenameFilter
{
    @Override
    public boolean accept(File dir, String name)
    {
        // 如果文件以。java结尾,或者文件对应一个路径,则返回true
        return name.endsWith(".java") || new File(name).isDirectory();
    }
}

2.3 注意点

Window使用反斜线(\)做路径分隔符,而在java中反斜线是转义字符,所以需要使用两条反斜线。
也可以使用斜线(/),java支持将斜线当成平台无关的路径分隔符;


3 流的分类

3.1 流向区分

站在内存所在的角度来区分的流向的
3.1.1 输入流
InputStream参见: 字节流 (基类)
Reader参见: 字符流 (基类)

3.1.2 输出流
OutputStream参见: 字节流 (基类)
Writer参见: 字符流 (基类)

3.2 流的数据单元

一个字节
一个字符

3.2.1 字节流
参见: InputStream (基类), OutputStream (基类)
FileInputStream

private static void byteRead()
    {
        FileInputStream inputStream = null;
        try
        {
            inputStream = new FileInputStream("src/com/gu/test/GetUserDir.java");
            byte[] buffer = new byte[1024];
            int hasRead = 0;
            while((hasRead = inputStream.read(buffer)) > 0)
            {
                System.out.println(new String(buffer, 0, hasRead));
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            if(inputStream != null)
            {
                try
                {
                    inputStream.close();
                }
                catch(IOException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
FileOutputStream

3.2.2 字符流
参见: Reader (基类), Writer (基类)
FileReader

private static void charRead()
    {
        FileReader fileReader = null;
        try
        {
            fileReader = new FileReader(new        File("src/com/gu/test/GetUserDir.java"));
            char[] buffer = new char[32];
            int hasRead = 0;
            while((hasRead = fileReader.read(buffer)) > 0)
            {
                System.out.println(new String(buffer, 0, hasRead));
            }
        }
        catch(Exception e)
        {
        }
        finally
        {
           if(fileReader != null)
            {
                try
                {
                    fileReader.close();
                }
                catch(IOException e)
                {
                   // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

FileWriter

3.2.3 使用规则
如果输入输出的是文本内容则使用字符流
如果输入输出的是二进制内容则使用字节流

3.3 流的角色

3.3.1 节点流
可以从/向一个特定的IO设备读/写数据的流,称为节点流 节点流属于低级流
当使用节点流的时候,程序直接连接到实际的数据源和实际的输入/输出节点

3.3.2 处理流
处理流使用一个已经存在的流进行连接或者封装,通过封装后的流实现数据读/写功能。处理流为高级流
处理流包装节点流是一种典型的装饰器设计模式,通过处理流包装不同的节点流,消除不同节点流的差异
优点:
提高了性能,使用了缓冲
操作便捷,一次处理大量内容
常见处理流
PrintStream
printStream的功能非常强大,通常如果我们要输出文本内容,就应该将输出流包装成printstream进行输出。

public static void main(String[] args)
    {
        FileOutputStream outputStream = null;
        PrintStream printStream = null;
        try
        {
            outputStream = new FileOutputStream("print.txt");
            printStream = new PrintStream(outputStream);
            printStream.println("ssss");
            printStream.println("saaaa");
        }
        catch(FileNotFoundException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if(outputStream != null)
            {
                try
                {
                    outputStream.close();
                }
                catch(IOException e)
                {
                    e.printStackTrace();
                }
            }
           if(printStream != null)
            {
                printStream.close();
            }
        }
    }
处理流的关闭
使用了处理流包装了底层的节点流之后,关闭输入/输出流的时候,只要关闭最上层的处理流即可。
关闭最上层的处理流的时候,系统会自动关闭底层的节点流.

4 转换流

4.1 InputStreamReader

将字节输入流转换成字符输入流

4.2 OutputStreamReader

将字节输出流转换成字符输出流

5 缓冲流

5.1 BufferedReader

bufferReader有一个readLine的方法,可以方便的一次读取一行,
会以换行符为标志。读不到会导致程序阻塞

6 推回输入流

6.1 两种类型

字节流:PushBackInputStream
字符流:PushBackReader
 public static void main(String[] args) throws IOException
    {
        @SuppressWarnings("resource")
        PushbackReader reader = new PushbackReader(new FileReader("src/com/gu/test/PushBackTest.java"), 64);
        try
        {
            char[] buffer = new char[32];
            String lastContent = "";
            int hasRead = 0;
            while((hasRead = reader.read(buffer)) > 0)
           {
                String content = new String(buffer, 0, hasRead);
                int targetIndex = 0;
                if((targetIndex = (lastContent + content).indexOf("new PushbackReader")) > 0)
                {
                    reader.unread((lastContent + content).toCharArray());
                    int len = targetIndex > 32 ? 32 : targetIndex;
                    reader.read(buffer, 0, len);
                    System.out.println(new String(buffer, 0, len));
                    System.exit(0);
                }
                else
                {
                    System.out.println(lastContent);
                    lastContent = content;
                }
            }
        }
        catch(Exception e)
        {
        }
    }

6.2 常用方法

void unread(byte[]/char[] buf)将一个字节/字符数组推回到缓冲区里,从而允许重复读取刚刚的内容
void unread(byte[]/char[] buf,int off,int len)
void unread(int b)将一个字节/字符推回到缓冲区里,从而允许重复读取

7 重定向标准输入/输出

public static void main(String[] args)
    {
        PrintStream printStream = null;
        try
        {
            // printStream = new PrintStream(new FileOutputStream("out.txt"));
            //重新设置了out方法
            // System.setOut(printStream);
            // System.out.println("hello");
            // System.out.println(new SystemOutTest());
            FileInputStream fis = new FileInputStream("print.txt");
            //重新设置了in()方法
            System.setIn(fis);
            Scanner sc = new Scanner(System.in);
            // sc.useDelimiter("\n");
            while(sc.hasNext())
            {
                System.out.println("content:" + sc.next());
            }
        }
        catch(FileNotFoundException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if(printStream != null)
            {
                printStream.close();
            }
        }
    }

8 java虚拟机读写其他进程的数据

此处的输入/输出流非常容易混淆,我们应该站在程序的角度,而不是子进程的角度
因此当试图让子进程读取程序中的数据,应该使用的是输出流
code:
public static void main(String[] args) throws IOException
    {
        // 运行javac返回运行该命令的子进程
        Process process = Runtime.getRuntime().exec("javac");
        // 以process进程的错误流创建BufferedReader对象
        // 这个错误流对本程序是输入流,对process则是输出流
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
        String buffer = null;
        while((buffer = reader.readLine()) != null)
        {
            System.out.println(buffer);
        }
    }

9 RandomAccessFile

java输入输出流中最丰富的文件内容访问类
支持随机访问模式,可以跳转到文件的任何位置
这就可以方便的从以有的文件后面追加内容

10 序列化

通过序列化可以将java对象存放在存储设备中,或者在网络上存储java对象
对象的序列化(Serialize)是指将对象写入IO流中,与此对应的,对象的反序列化(Deserialize)是指从IO流中恢复Java对象

10.1 递归序列化

如果被序列化的对象Field中有引用对象,那么这个引用对象也要是可序列化的对象,如果引用对象中还有引用对象,那么那个引用对象的引用对象也要是可序列化的,这就是递归序列化

10.2 注意点

注意点1
1.反序列化无需使用构造器生成java对象
2.当一个类有多个父类时,那么这个父类要么可以序列化,要么有无参构造器,并且当父类时无参构造器的时候,父类的Field将不会被二进制,即父类的Field将不会被赋值
注意点2
由于java序列化的机制,如果多次序列化同一个对象,只有在第一次序列化的时候才会把该对象转换成字节流并输出。后面,即使那个对象的field的值发生了改变,也只会输出序列化编号

10.3 自定义序列化:Serializable

transient
被transient修饰的field将不会被序列化,并且transient关键字只能修饰Field

实现自定义序列化
在进行自定义序列化的时候,会先调用writeReplace方法,如果这个方法返回一个对象,将继续调用那个对象的writeReplace方法,直到该方法不再返回一个对象为止。。。
程序最后将调用writeObJect方法来保存该对象状态。
重写writeObject和readObject方法

code:

public class Person implements Serializable
{
    private static final long serialVersionUID = -1456822345003300001L;
    private String name;
    private int id; 
    public Person(String name, int id)
    {
        super();
        this.name = name;
        this.id = id;
    }
     ....
    //在自定义序列化中可以实现一些加密规则
    private void writeObject(ObjectOutputStream out) throws IOException
    {
        out.writeObject(new StringBuffer(name).reverse());
        out.writeInt(id);
    }
    private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException
    {
        // this.name = ((StringBuffer) in.readObject()).reverse().toString();
        this.name = ((StringBuffer) in.readObject()).toString();
        this.id = in.readInt();
    }
}

//write和read操作field的顺序要一直,否则将无法正确执行
writeReplace

public class Person implements Serializable
{
    private static final long serialVersionUID = -1456822345003300001L;
    private String name;
    private int id;
    public Person(String name, int id)
    {
        super();
        this.name = name;
        this.id = id;
    }
......
    //完全自定义序列化,将person对象,序列化成一个list
    protected Object writeReplace() throws ObjectStreamException
    {
        List<Object> list = new ArrayList<>();
        list.add(name);
        list.add(id);
        return list;
    }
}

readResolve
这个方法会紧接着readObject方法之后被调用,该方法的返回值将会代替原来反序列化的对象,而原来反序列化对象将会被立即丢弃

public class Orientation implements Serializable
{
    private static final long serialVersionUID = -6673976809257572168L;
    public static final Orientation HOR = new Orientation(1);
    public static final Orientation VER = new Orientation(2);
    private int value;
    private Orientation(int value)
    {
        this.value = value;
    }
    private Object readResolve() throws ObjectStreamException
    {
        if(value == 1)
        {
            return HOR;
        }
        else if(value == 2)
        {
            return VER;
        }
        return null;
   }
   }
由于反序列化生成对象不需要构造方法,所以这里即使Orientation的构造方法是private的,序列化也能生成一个新的Orientation对象。这就会导致序列化生成的对象,与之前传入的对象不是同一个。
利用readResolve方法可以解决这个问题。

10.4 自定义序列化:Externalizable

Externalizable接口相比较Serializable,会强制要求实现重写两个自定义的方法,重写writeObject和readObject方法

public class Person implements Externalizable
{
    private String name;
    private int age;
    public Person()
    {
    } 
    public Person(String name, int age)
   {
        System.out.println("有参数的构造器");
        this.name = name;
        this.age = age;
   } 
   ....
    @Override
    public void writeExternal(ObjectOutput out) throws IOException
    {
        out.writeObject((new StringBuffer(name)).reverse());
        out.writeInt(age);
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
    {
        this.name = ((StringBuffer) in.readObject()).toString();
        this.age = in.readInt();
    }
}

10.5 两种序列化接口对比

10.6 版本

serialVersionUID:用来保证两个class文件的兼容性
如果升级一个类,他它的serialVersionUID不变,那么序列化机制会把他们当成同一个序列化版本。
如果类的修改会导致反序列化失败,那么应该为其重新分配一个serialVersionUID。


11 NIO

参见: java7的NIO (升级版)
java 7 提供了一套全新的API 可以更加高效的进行输入输出操作

11.1 传统IO

1.传统IO是阻塞式的。
2.传统IO的底层都是以字节读取为单位的

11.2 新IO

新IO与传统IO的最大的区别就是新IO提供了一个map()方法,通过该map()方法,可以直接将“一块数据"映射到内存中。
传统IO系统是面向流的处理,新的IO则是面向块的处理
核心类
通道:Channel

类似于传统的流对象
1.可以将文件部分或者全部直接映射成Buffer
2.程序不能直接访问Channel中的数据,包括读和写,它只能和Buffer进行交互。如果要从一个Channel中读取数据,必须先用Buffer从Channel中读取数据,然后让程序从Buffer中读取数据;同样的,如果要向Channel中写入数据,就要先将数据放入到Buffer中,程序再将Buffer的数据写入到Channel中。

Channel对象的获取
通过传统节点InputStream、OutputStream的getChannel()方法获取;

不同的节点获取到到的Channel对象不一样:比如:FileInputStream和FileOutputStream获取到的就是FileChannel

常用方法
map()将Channel对应的部分或者全部映射成Buffer
read(){一系列重载形式}
write(){一系列重载形式}
示例代码
1:FileInputStream获取channel
public static void main(String[] args) throws FileNotFoundException
    {
        File file=new File("Test.java");
        FileInputStream fis=new FileInputStream(file);
        FileChannel inChannel=fis.getChannel();
        FileChannel outChannel=new FileOutputStream("channel.txt").getChannel();
        try
        {
            MappedByteBuffer buffer =inChannel.map(FileChannel.MapMode.READ_ONLY, 0, file.length());            
            outChannel.write(buffer);   
            buffer.clear();
            Charset charset=Charset.forName("utf-8");
            CharsetDecoder decoder=charset.newDecoder();    
            //change byteBuffer to charBuffer
            CharBuffer charBuffer=decoder.decode(buffer);
            System.out.println(charBuffer);
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }
2:RandomAccessFile获取channel
public static void main(String[] args) throws FileNotFoundException
    {
        File file=new File("out.txt");
        RandomAccessFile accessFile=new RandomAccessFile(file, "rw");
        FileChannel fileChannel=accessFile.getChannel();
        try
        {
            MappedByteBuffer buffer=fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, file.length());            
            fileChannel.position(file.length());           
            fileChannel.write(buffer);          
        }
        catch(IOException e)
        {
            // TODO Auto-generated catch block  
            e.printStackTrace();
        }
    }

3:多次获取channel中的值

 public static void main(String[] args) throws IOException
    {
        FileInputStream fis = new FileInputStream("Test.java");
        FileChannel channel = fis.getChannel();
        //set buffer size
        ByteBuffer buffer = ByteBuffer.allocate(64);
        while(channel.read(buffer) != -1)
        {
            // lock clear area
            buffer.flip();
            Charset charset = Charset.forName("utf-8");
            CharsetDecoder decoder = charset.newDecoder();
            CharBuffer charBuffer = decoder.decode(buffer);
            System.out.print(charBuffer);
////initialize buffer
           buffer.clear();
        }
    }

缓冲:Buffer

public static void main(String[] args)
    {
        CharBuffer buffer=CharBuffer.allocate(8);
        System.out.println("capacity==>"+buffer.capacity());
        System.out.println("limit==>"+buffer.limit());
        System.out.println("position==>"+buffer.position());       
        buffer.put('a');
        buffer.put('b');
        buffer.put('c');        
        System.out.println("position after added three elements==>"+buffer.position());    
        buffer.flip();
        System.out.println("limit after do flip==>"+buffer.limit());
        System.out.println("position after do flip==>"+buffer.position());       
        //get first element
        //Relative get
        System.out.println("the element at positon 1==>"+buffer.get());
        System.out.println("position after get first element==>"+buffer.position());       
        buffer.clear();
        System.out.println("limit after do clear==>"+buffer.limit());
        System.out.println("position after do clear==>"+buffer.position());
        // absolutely get
        System.out.println("the element at position 3 after clear==>"+buffer.get(2));
        System.out.println("get position after absoultly get==>"+buffer.position());      
    }
方法:
flip():将limit设置为position ,并将position设置为0为从buffer中读取数据做好准备相当于把buffer没有数据的部分封印了起来,这样就可以防止读到null
clear():不是清空buffer将limit设置为capacity,将position设置为0;为再次向buffer中装入数据做好准备
get()和put():相对会改变position;绝对不会改变position
allocateDirect():用此方法可以创建直接buffer只有byteBuffer提供了这个方法
直接Buffer创建的成本比较高,但读取效率高,所以它只使用于长期存在的Buffer,而不适用于那些短期的一次性用完的Buffer

11.3 字符集和Charset

计算机内的所有文件,图片,数据都是一种表象,所有文件在底层都是二进制文件,即全部都是字节码;

11.3.1 编码和解码

11.3.2 Charset

 public static void main(String[] args) throws CharacterCodingException
    {
        Charset charset=Charset.forName("utf-8");
        CharsetEncoder encoder=charset.newEncoder();
        CharsetDecoder decoder=charset.newDecoder();       
        CharBuffer buffer=CharBuffer.allocate(8);
        buffer.put('孙');
        buffer.put('悟');
        buffer.put('空');     
        buffer.flip();
        System.out.println(buffer.limit());
        ByteBuffer byteBuffer=encoder.encode(buffer);     
        System.out.println(byteBuffer.limit()+"**"+byteBuffer.capacity());
        for(int i=0;i<byteBuffer.limit();i++){
            System.out.print(byteBuffer.get(i)+"");
        }
        System.out.println("");
        System.out.println(""+decoder.decode(byteBuffer));
    }
方法:获取系统支持的所有编码
availableCharsets
public static void main(String[] args)
   {
        SortedMap<String, Charset> map=Charset.availableCharsets();
       System.out.println(map.keySet());
    }
11.3.3 字符集
字符集就是大家约定的一个字符编号集

11.4 文件锁:FileLock

通过FileChannel对象的lock和tryLock方法可以获取到FileLock对象
不同点:lock会阻塞;  tryLock方法不会阻塞
直接调用lock和trylock的无参方法获取到的是排他锁

code:

public static void main(String[] args) throws IOException, InterruptedException
    {
         File file=new File("Test.java");
         FileInputStream fis=new FileInputStream(file);
         FileChannel channel=fis.getChannel();
         FileLock fileLock=channel.tryLock();         
         Thread.sleep(10000);       
         fileLock.release();
    }
注意建议
虽然使用文件锁可以控制并发操作文件,
但是对于高并发访问的情形,还是应该使用数据库进行数据存储 
文件锁归java虚拟机所有。

12 java7的NIO

12.1Path/Paths

public static void main(String[] args) {
    Path path = Paths.get(".");
    System.out.println("path's dir num==>" + path.getNameCount());
    System.out.println("path's root==>" + path.getRoot());
    Path absolutelyPath=path.toAbsolutePath();
    System.out.println("absolutelyPath==>"+absolutelyPath);
    System.out.println("absolutelyPath's root path==>"+absolutelyPath.getRoot());
    System.out.println("absolutelyPath's root num==>"+absolutelyPath.getNameCount());
    System.out.println(absolutelyPath.getName(2)+"");
    Path path2=Paths.get("g:", "publish","codes");
    System.out.println(path2);
}

12.2File/Files

public static void main(String[] args) throws IOException {
    List<String> poem=new ArrayList<>();
    poem.add("aaaaa");
    poem.add("bbbb");
    Files.write(Paths.get("test.txt"), poem, Charset.forName("utf-8"));
    FileStore cStore=Files.getFileStore(Paths.get("C:"));
    System.out.println("C:totalStore==>"+cStore.getTotalSpace());
    System.out.println("C:useableStore==>"+cStore.getUsableSpace());
}

封装了大量的文件操作方法

12.3FileVisitor

用来优雅的遍历文件和子目录
walkFileTree(Path start,FileVistor

public static void main(String[] args) throws IOException {
    Files.walkFileTree(Paths.get("f:", "webServer", "ch15"),
    new FileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(Path dir,
            BasicFileAttributes attrs) throws IOException {
            System.out.println("now is visit dir==>" + dir);
            return FileVisitResult.CONTINUE;
        }
        @Override
        public FileVisitResult visitFile(Path file,
            BasicFileAttributes attrs) throws IOException {
            System.out.println("now is visit file==>" + file);
            if (file.endsWith("FileVistorTest.java")) {
                System.out.println("------get aim file------");
                return FileVisitResult.TERMINATE;
            }
            return FileVisitResult.CONTINUE;
        } 
        @Override
        public FileVisitResult visitFileFailed(Path file,
            IOException exc) throws IOException {
            return FileVisitResult.TERMINATE;
        }
        @Override
        public FileVisitResult postVisitDirectory(Path dir,
            IOException exc) throws IOException {
            return FileVisitResult.CONTINUE;
        }
        });
}

walkFileTree(Path start ,Set options ,int maxDepth,FileVistor

12.4WatchService

之前的jdk版本中,如果要监听文件的变化,需要开启一个线程,定时去遍历所有的文件,然后比对目录文件。
在java7 nio2中,提供了regsiter(Watch Service ,WatchEvent.Kind<?> ...extents ) 注册监听服务,
然后就可以使用watchService下的方法;
WatchKey poll():获取下一个WatchKey,如果没有则立即返回null
WatchKey poll(long timeout,TimeUnit unit):尝试等待timeout时间,获取下一个WatchKey
WatchKey take():获取一个key,如果没有Watchkey发生就一直等下去
适合一直运行的任务

code

public static void main(String[] args) throws IOException,
InterruptedException {
    WatchService service = FileSystems.getDefault().newWatchService();
    Paths.get("C:/").register(service,StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_DELETE,StandardWatchEventKinds.ENTRY_MODIFY);
    while (true) {
    WatchKey key = service.take();
    for (WatchEvent<?> event : key.pollEvents()) {
    System.out.println(event.context() + "文件发生了" + event.kind()+ "事件");
    }
    boolean valid = key.reset();
    if (!valid) {
    break;
    }
    }
}

12.5访问文件属性

public static void main(String[] args) throws IOException {
Path path = Paths.get("f:", "webServer", "ch15", "src", "com", "gu",
"test3", "AttributeViewTest.java");
// get basicView
BasicFileAttributeView basicFileAttributeView = Files.getFileAttributeView(path, BasicFileAttributeView.class);
BasicFileAttributes basicFileAttributes = basicFileAttributeView.readAttributes(); 
System.out.println("create time==>"+ basicFileAttributes.creationTime());
System.out.println("last visit time==>"+ basicFileAttributes.lastAccessTime());
System.out.println("last modify time==>"+ basicFileAttributes.lastModifiedTime()); 
FileOwnerAttributeView fileOwnerAttributeView = Files.getFileAttributeView(path, FileOwnerAttributeView.class);
System.out.println(fileOwnerAttributeView.getOwner());
// get guest user
UserPrincipal user = FileSystems.getDefault().getUserPrincipalLookupService().lookupPrincipalByName("guest");
fileOwnerAttributeView.setOwner(user);
System.out.println(fileOwnerAttributeView.getOwner());
UserDefinedFileAttributeView userView = Files.getFileAttributeView(path, UserDefinedFileAttributeView.class);
userView.write("发行者", Charset.defaultCharset().encode("JAVA发展联盟"));
List<String> list = userView.list();
System.out.println(list.size());
for (String name : list) {   
ByteBuffer byteBuffer = ByteBuffer.allocate(userView.size(name));
userView.read(name, byteBuffer);
byteBuffer.flip();
String value = Charset.defaultCharset().decode(byteBuffer)
.toString(); 
System.out.println(name + "--->" + value);
}
DosFileAttributeView dosFileAttributeView = Files.getFileAttributeView(
path, DosFileAttributeView.class);
dosFileAttributeView.setHidden(true);
dosFileAttributeView.setReadOnly(true);
}

文件的编辑时间
文件的所有者
文件的隐藏读写属性(Dos属性)


13 注意点

13.1 不同平台换行符

windows使用\r\n作为换行符
UNIX/Linux/BSD使用\n作为换行符
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值