文件File详解

前言

博主github

博主个人博客http://blog.healerjean.com

习惯了使用OSS傻瓜式上传,是不是都快忘记写原生的上传了,今天小米的项目中需要用一下,所以之类简单总结下 吧

1、File

1.1、创建文件

  • 1、路径不存在,fileNameTxt.createNewFile() 会抛出异常
  • 2、只有路径,不会创建出文件,也不会报错,无法创建,但是不会报错
  • 3、路径存在,文件不存在,创建成功
  • 4、没有路径,只有文件文件名,和则创建的文件和src一个级别,创建成功
   /**
     * 1、路径不存在,fileNameTxt.createNewFile() 会抛出异常
     * 2、只有路径,不会创建出文件,也不会报错,无法创建,但是不会报错
     * 3、路径存在,文件不存在,创建成功
     * 4、没有路径,只有文件文件名,和则创建的文件和src一个级别,创建成功
     */
    @Test
    public void createFile() throws IOException {
        String filePath = "newFile.txt";
        File fileNameTxt = new File(filePath);
        if (!fileNameTxt.exists()) {
            fileNameTxt.createNewFile();
        }
        log.info("创建成功");
    }

1.2、具备目录,创建文件

   /**
     * 2、创建有目录的文件
     * 通过父的目录引入文件   directoryName 是父类
     */
    @Test
    public void createHavaDirectoryFile() throws IOException {
        String directoryName = "D:/test/file/d02_createHavaDirectoryFile";
        String fileName = "directoryName.txt";
        File directoryNameTxt = new File(directoryName, fileName);
        if (!directoryNameTxt.exists()) {
            directoryNameTxt.createNewFile();
        }
        log.info("创建有目录的文件成功");
    }

1.3、判断文件、目录

   /**
     * 3、 判断文件、目录
     */
    @Test
    public void judgeFileOrDirectory() {
        File file = new File("D:/test/file/d02_createHavaDirectoryFile");
        log.info("测试开始");
        if (file.isFile()) {
            log.info(file.getPath() + "是一个文件");
        } else if (file.isDirectory()) {
            log.info(file.getPath() + "是一个目录");
        } else {
            log.info(file.getPath() + "不是文件也不是目录");
        }
    }

1.4、创建目录

  • 创建目录,即使路径不存在,也会创建相关路径,因为是mkdirs
   /**
     * 3、创建目录
     * 判断是不是目录
     * 创建目录,即使路径不存在,也会创建相关路径,因为是mkdirs
     */
    @Test
    public void createDirectory() {
        //引入目录
        File directoryName = new File("D:/test/healerjean/file");
        if (!directoryName.exists()) {
            directoryName.mkdirs();
            log.info(directoryName.getPath() + "创建目录成功");
        }
    }

1.5、普通复制文件

  • 第一个文件以及路径必须存在, 否则fileInputStream会报错
  • 第二个文件可以不存在,但是路径必须存在,如果路径不存在则new FileOutputStream会报错
    /**
     * 5、复制文件
     * Input第一个文件以及路径必须存在, 否则 FileOutputStream out = new FileOutputStream(outFilePath); FileNotFoundException 异常
     * Output第二个文件可以不存在,但是路径必须存在,如果路径不存在则FileOutSteam会报错
     */
    public void copyFile() throws IOException {
        String inFilePath = "D:/test/file/d03_copyFile/exist/file.txt";
        String outFilePath = "D:/test/file/d03_copyFile/no_exist/newfile.txt";

        FileInputStream ins = new FileInputStream(inFilePath);
        FileOutputStream out = new FileOutputStream(outFilePath);
        byte[] b = new byte[1024];
        int n = 0;
        while ((n = ins.read(b)) != -1) {
            out.write(b, 0, n);
        }
        ins.close();
        out.close();
        log.info("复制文件成功");
    }

1.6.1、递归整个目录

  • file.listFiles() 是获取file这个对象也就是file这个目录下面的文件和文件夹的集合
    /**
     * 6、递归遍历整个目录的文件
     * file.listFiles()是获取file这个对象也就是file这个目录下面的文件和文件夹的集合
     */
    public void cycleFiles(File file) {
        File[] files = file.listFiles();
        for (File sonFile : files) {
            if (sonFile.isDirectory()) {
                cycleFiles(sonFile);
            } else {
                log.info(sonFile.getAbsolutePath());
            }
        }
        log.info(file.getAbsolutePath());
    }
    @Test
    public void testCycleFiles() {
        File file = new File("D:/test");
        cycleFiles(file);
    }

1.6.2、 递归递归整个目录,并读取文件内容进行匹配

/**
     * 6.2 、递归目录,读取文件内容进行匹配
     * size :用于保留统计记录的个数
     */
    private static int size = 1;
    public void cycleFileContent(File file, String content) throws Exception {
        File[] files = file.listFiles();
        for (File f : files) {
            if (f.isDirectory()) {
                cycleFileContent(f, content);
            } else {
                String path = f.getPath();
                FileInputStream fileInputStream = new FileInputStream(f);
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = fileInputStream.read(buffer)) != -1) {
                    outStream.write(buffer, 0, len);
                }
                String str = new String(outStream.toByteArray(), "utf-8");
                if (str.contains(content)) {
                    log.info("第【{}】个文件匹配到内容,路径为:{}", size, f.getPath());
                    size++;
                }
            }
        }
    }
    @Test
    public void testCycleFileContent() throws Exception {
        File file = new File("D:/test");
        String content = "co";
        cycleFileContent(file, content);
    }

1.7.1、读取文件内容

1.7.2、读取整个文件内容,转化为ByteArrayOutputStream读取

/**
* 7.1、读取文件内容:转化为ByteArrayOutputStream读取
*/
@Test
public void readFileContent() throws Exception {
    File file = new File("D:\\test\\file\\file.txt");
    FileInputStream fileInputStream = new FileInputStream(file);
    ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
    int len = 0;
    byte[] buffer = new byte[1024];
    while ((len = fileInputStream.read(buffer)) != -1) {
        byteOutputStream.write(buffer, 0, len);
    }
    String txtValue = new String(byteOutputStream.toByteArray(), "utf-8");
    log.info(txtValue);
}

1.7.2、一行一行读取文件内容

  • new BufferedReader(new InputStreamReader(new ByteArrayInputStream(txtByteArray), “utf-8”));
    /**
     * 7.读取文件内容
     * 7.2、按照行,一行一行读取txt内容
     */
    @Test
    public void readFileLineContent() throws Exception {
        File file = new File("D:\\test\\file\\file.txt");
        FileInputStream fileInputStream = new FileInputStream(file);
        ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = fileInputStream.read(buffer)) != -1) {
            byteOutputStream.write(buffer, 0, len);
        }
        byte[] txtByteArray = (byteOutputStream.toByteArray());
        BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(txtByteArray), "utf-8"));
        String lineContent = null;
        int line = 0;
        while ((lineContent = reader.readLine()) != null) {
            line++;
            log.info("第【{}】行的内容为:{}", line, lineContent);
        }
    }

1.8、根据字符串生成内容

  /**
     * 8、根据内容生成文件
     */
    @Test
    public void contentToFile() throws Exception {
        String content = "我是大好人";
        String fileName = UUID.randomUUID().toString().replace("-", "") + ".txt";
        FileOutputStream outputStream = new FileOutputStream("D:/test/" + fileName);
        byte[] buffer = content.getBytes("utf-8");
        outputStream.write(buffer);
        log.info("文件【{}】创建成功", fileName);
        outputStream.close();
    }

1.9、局域网文件调用

File file = new File("//192.168.31.1/file");

2、上传下载

2.1、上传


@ApiOperation(
    value = "文件上传",
    notes = "文件上传",
    consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
    produces = MediaType.APPLICATION_JSON_UTF8_VALUE,
    response = String.class)
@PostMapping(value = "upload", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public String upload(MultipartFile file) {
    log.info("文件管理--------文件上传--------请求参数{}", file);
    //1、确定文件存储目录
    String javaIoTmpdir = System.getProperty("java.io.tmpdir");
    File tempFile = new File(javaIoTmpdir);
    if (!tempFile.exists()) {
        tempFile.mkdirs();
    }

    // 2、文件上传
    String fileName = file.getOriginalFilename();
    File outFile = new File(tempFile, fileName);
    // InputStream inputStream = null;
    // FileOutputStream fileOutputStream = null;
    try {
        // 1、inputstream -> 本地文件
        FileUtils.copyInputStreamToFile(file.getInputStream(), outFile);

        // 2、MultipartFile文件  -> 本地文件
        // file.transferTo(outFile);

        // 3、MultipartFile 文件获取字节 -> OutputStream
        // byte[] bytes = file.getBytes();
        // fileOutputStream = (new FileOutputStream(outFile));
        // fileOutputStream.write(bytes);

        // 4、InputStream -> OutputStream
        // inputStream = file.getInputStream();
        // fileOutputStream = (new FileOutputStream(outFile));
        // IOUtils.copy(inputStream, fileOutputStream);

        log.info("文件管理--------文件上传成功--------上传文件名{}", file.getOriginalFilename());
    } catch (IOException e) {
        log.info("文件上传失败");
        throw new RuntimeException("文件上传失败", e);
    } finally {
        log.info("准备开始关闭流");
        // try {
        //     if (fileOutputStream != null) {
        //         fileOutputStream.close();
        //     }
        // } catch (IOException e) {
        //     log.error("流关闭失败", e);
        // }
        // try {
        //     if (inputStream != null) {
        //         inputStream.close();
        //     }
        // } catch (IOException e) {
        //     log.error("流关闭失败", e);
        // }
    }
    return fileName;
}

2.2、下载

    @ApiOperation(
            value = "文件下载",
            notes = "文件下载",
            consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE,
            response = String.class)
    @GetMapping(value = "download/{fileName}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void downLoad(HttpServletResponse response, @PathVariable String fileName, Boolean preview) {
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            log.info("文件管理--------文件下载--------请求参数{}", fileName);
            String javaIoTmpdir = System.getProperty("java.io.tmpdir");
            File file = new File(javaIoTmpdir, fileName);
            if (!file.exists()) {
                throw new BusinessException("文件不存在");
            }
            inputStream = new FileInputStream(file);
            outputStream = response.getOutputStream();
            if (preview != null && !preview) {
                //强制浏览器下载
                log.info("文件管理--------强制浏览器下载--------文件名{}", fileName);
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            } else {
                log.info("文件管理--------文件预览--------文件名{}", fileName);
                //浏览器尝试打开,支持office online或浏览器预览pdf功能
                response.setHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            }
            IOUtils.copy(inputStream, outputStream);
        } catch (Exception e) {
            log.info("文件:{},下载失败", fileName, e);
            throw new RuntimeException("文件上传失败", e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("inputStream未正确关闭");
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error("outputStream未正确关闭");
                }
            }
        }
    }

3、流相关

3.1、流/文件复制

3.1.1、inputstream -> 本地文件

  • copyInputStreamToFile(InputStream source, File destination)
File localFile = new File(tempFile,fileName);
FileUtils.copyInputStreamToFile(file.getInputStream(),localFile);

3.1.2 源文件 -> 本地文件

3.1.2.1、MultipartFile文件 -> 本地文件

  • transferTo(File var1)
File localFile = new File(tempFile,fileName);
file.transferTo(localFile);

3.1.2.2、File文件 ->本地文件

 FileUtils.copyFile(File srcFile, File destFile)

3.1.3、MultipartFile 文件获取字节 -> OutputStream

byte[] bytes = file.getBytes();
File localFile = new File(tempFile,fileName);
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(localFile));
stream.write(bytes);

3.1.4、InputStream -> OutputStream

  • IOUtils.copy(inputStream, outputStream);
IOUtils.copy(inputStream, outputStream);
inputStream.close();
outputStream.close();

3.1.5、文件Url -> InputStream

URL url = new URL(StringEscapeUtils.unescapeHtml(netUrl));

HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setConnectTimeout(30*1000);
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

InputStream  stream = conn.getInputStream();

3.1.6、图片Url -> OutStream

URL urlStr = new URL(url);
BufferedImage bufferedImage = ImageIO.read(urlStr);

ImageIO.write(bufferedImage, "jpg", response.getOutputStream());

4、流关闭

4.1、流为什么一定要关闭

首先需要明白的一点是GC是回收内存的,关于文件。网络Io,它是属于系统资源的

因为GC只管内存不管别的资源,GC只能回收内存。假如有内存以外的其它资源依附在Java对象上,比如文件,比如输入输出设备(键盘/屏幕等),等等。这些是不能自动关闭

一般情况下是:先打开的后关闭,后打开的先关闭

  1. 包装关系:可以只关闭处理流(包装流),不用关闭节点流。处理流关闭的时候,会调用其处理的节点流的关闭方法。

  2. 依赖关系,如果流a依赖流b,应该先关闭流a,再关闭流b。例如,处理流a依赖节点流b,应该先关闭处理流a,再关闭节点流b

节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader.
处理流(包装流):是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。

4.2、流的正确关闭姿势

4.2.1、try catch,要在finaly 中关闭流

 /**
     * 1.1、try catch,要在finaly 中关闭流
     */
    @Test
    public void test1() {

        File file = new File("/Users/healerjean/Desktop/test/file.txt");
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(file);
            //TODO 操作代码
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    log.error("fileOutputStream未正确关闭");
                }
            }
        }
    }

4.2.2、应该在循环中关闭流,不应该在循环外


    /**
     * 1.2、应该在循环中关闭流,如下
     */
    @Test
    public void closeStream2() {
        for (int i = 0; i < 100; i++) {
            FileOutputStream fileOutputStream = null;
            try {
                fileOutputStream = new FileOutputStream("/Users/healerjean/Desktop/test/file.txt");
                //TODO 操作代码
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage(), e);
            } finally {
                if (fileOutputStream != null) {
                    try {
                        fileOutputStream.close();
                    } catch (IOException e) {
                        log.error("fileOutputStream未正确关闭");
                    }
                }
            }
        }
    }

4.2.3、java7解锁关闭流新姿势

引入了, OutputStream implements Closeable ,所以直接在try里面写上对于的流就可以关闭



    /**
     * 1.3、java7解决关闭流新姿势
     * 只要实现的自动关闭接口(Closeable)的类都可以在try结构体上定义,java会自动帮我们关闭,及时在发生异常的情况下也会。可以在try结构体上定义多个,用分号隔开即可,如:
     */
    @Test
    public void java6CloseStream() {
        try (FileOutputStream fileOutputStream = new FileOutputStream("/Users/healerjean/Desktop/test/file.txt"); FileInputStream fileInputStream = new FileInputStream("/Users/healerjean/Desktop/test/file.txt");) {
            //TODO 操作代码
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

4.3、可以只关闭处理流(包装流),包装流的close方法是会自动关闭被包装的流

4.3.1、测试代码


    @Test
    public void baozhuang(){
        FileOutputStream fileOutputStream = null;
        BufferedOutputStream bufferedOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream("/Users/healerjean/Desktop/test/file.txt");
            bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
            bufferedOutputStream.write("test write something".getBytes());
            bufferedOutputStream.flush();

        }catch (Exception e){
            if(bufferedOutputStream !=null){
                //从包装流中关闭流
                try {
                    bufferedOutputStream.close();
                } catch (IOException ex) {
                    log.error("fileOutputStream未正确关闭",ex);
                }
            }
        }
        log.info("已经正确关闭了流");

    }

4.3.2、测试代码拆解

1、观察new BufferedOutputStream(fileOutputStream);
  • BufferedOutputStream 继承自FilterOutputStream (一定要看清不是FileOutputStream),它并没有重写close方法,而是直接使用的FilterOutputStream里面的close方法,

  • 一定要看清在try里面使用了关闭流的新姿势


class FilterOutputStream extends OutputStream {
  @SuppressWarnings("try")
    public void close() throws IOException {
        try (OutputStream ostream = out) {
            flush();
        }
    }
    
  • BufferedOutputStream的构造器直接将FileOutputStream作为属性传入了,通过上面的源码可以知道是在flush()结束之后关闭的是FileOutputStream 文件流


public class BufferedOutputStream extends FilterOutputStream { ...

 public BufferedOutputStream(OutputStream out) {
        this(out, 8192);
    }
    
  • 观察FileOutputStream的close方法,可以看出它采用同步锁,而且使用了关闭标记,如果已经关闭了则不会再次操作,所以多次调用不会出现问题。也就是重复调用close()方法不会出问题

class FileOutputStream extends OutputStream{

  public void close() throws IOException {
        synchronized (closeLock) {
            if (closed) {
                return;
            }
            closed = true;
        }

        if (channel != null) {
            channel.close();
        }

        fd.closeAll(new Closeable() {
            public void close() throws IOException {
               close0();
           }
        });
    }

4.3.3、结论

包装的流都会自动调用被包装的流的关闭方法,无需自己调用,也就是说包装流并不是什么流,归根结底,最底层的文件流才是正儿八经的流,通过上面的源码也可以看出,有关包装流重复调用包装流和文件流close()方法不会出问题。

4.4、依赖关系关闭是是有顺序的

4.4.1、测试代码

直接调用会抛异常


   /**
     * 2、流的关闭顺序
     * 2.2、依赖关系
     */
    @Test
    public void baozhuang2() throws Exception {
        FileOutputStream fileOutputStream = null;
        BufferedOutputStream bufferedOutputStream = null;
        fileOutputStream = new FileOutputStream("/Users/healerjean/Desktop/test/file.txt");
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
        BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
        bufferedWriter.write("java IO close test");

        // 从内带外顺序顺序会报异常
        fileOutputStream.close();
        outputStreamWriter();
        bufferedWriter.close();//会抛异常
        log.info("已经正确关闭了流");

    }
    
    
    
    
    java.io.IOException: Stream Closed

	at java.io.FileOutputStream.writeBytes(Native Method)
	at java.io.FileOutputStream.write(FileOutputStream.java:326)
	at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
	at sun.nio.cs.StreamEncoder.implClose(StreamEncoder.java:316)
	at sun.nio.cs.StreamEncoder.close(StreamEncoder.java:149)
	at java.io.OutputStreamWriter.close(OutputStreamWriter.java:233)
	at java.io.BufferedWriter.close(BufferedWriter.java:266)
	at com.healerjean.proj.a_test.d03_流关闭.baozhuang2(d03_流关闭.java:128)
	

4.4.2、拆解分析

  • 观察BufferedWriter的关闭源码,可以看到它是直接调用的out也就是文件流FileOutputStream流,而我们先关闭了FileOutputStream流,所以肯定会抛出异常,流已经关闭
public class BufferedWriter extends Writer 

    public void close() throws IOException {
        synchronized (lock) {
            if (out == null) {
                return;
            }
            try (Writer w = out) {
                flushBuffer();
            } finally {
                out = null;
                cb = null;
            }
        }
    }
    
    
      void flushBuffer() throws IOException {
        synchronized (lock) {
            ensureOpen();
            if (nextChar == 0)
                return;
            out.write(cb, 0, nextChar);
            nextChar = 0;
        }
    }
    
    

    
  • 正确写法


    /**
     * 2、流的关闭顺序
     * 1、依赖关系
     */
    @Test
    public void baozhuang2() throws Exception {
        FileOutputStream fileOutputStream = null;
        BufferedOutputStream bufferedOutputStream = null;
        fileOutputStream = new FileOutputStream("/Users/healerjean/Desktop/test/file.txt");
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
        BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
        bufferedWriter.write("java IO close test");

        // // 从内带外顺序顺序会报异常
        // fileOutputStream.close();
        // outputStreamWriter.close();
        // bufferedWriter.close(); //会抛异常


        // 正确关闭姿势
        bufferedWriter.close();
        outputStreamWriter.close();
        fileOutputStream.close();
        log.info("已经正确关闭了流");

    }




4.4.3、结论

依赖关系:如果流a依赖流b,应该先关闭流a,再关闭流b。例如,处理流a依赖节点流b,应该先关闭处理流a,再关闭节点流b

4.5、Flush是干什么的

Stream也提供了close()方法关闭输出流,以便释放系统资源。要特别注意:OutputStream还提供了一个flush()方法,它的目的是将缓冲区的内容真正输出到目的地。

4.5.1、为什么要有flush

因为向磁盘、网络写入数据的时候,出于效率的考虑,操作系统并不是输出一个字节就立刻写入到文件或者发送到网络,而是把输出的字节先放到内存的一个缓冲区里(本质上就是一个byte[]数组)

等到缓冲区写满了,再一次性写入文件或者网络,OutputStream有个flush()方法**,能强制把缓冲区内容输出**。

4.5.2、一定要调用吗

通常情况下,我们不需要调用这个flush()方法,因为缓冲区写满了OutputStream会自动调用它,并且,在调用close()方法关闭OutputStream之前,也会自动调用flush()方法。

  • 但是,在某些情况下,我们必须手动调用flush()方法

小明正在开发一款在线聊天软件,当用户输入一句话后,就通过OutputStream的write()方法写入网络流。小明测试的时候发现,发送方输入后,接收方根本收不到任何信息?

原因就在于写入网络流是先写入内存缓冲区,等缓冲区满了才会一次性发送到网络。如果缓冲区大小是4K,则发送方要敲几千个字符后,操作系统才会把缓冲区的内容发送出去,这个时候,接收方会一次性收到大量消息。

4.5.3、close 和 flush (结论)

flush()方法
		 1.用来刷新缓冲区,刷新后可以再次写出,这个典型的应用可以脑补下QQ即时聊天场景就好
close()方法
		 2.用来关闭流释放资源
	    3.如果是带缓冲区的流对象的close()方法,不但会关闭流,还会在关闭流之前刷新缓冲区,关闭之后不能再写入


所以,不能用close来代替flush 

一般情况下,我们也可以使用close来进行刷新,通过看close方法的源码,发现close方法里面包含一个flush方法。flush就是刷新缓冲区的功能,所以,我们可以总结close方法的作用或者特点是:

具备刷新功能,在关闭流之前,就会先刷新一次缓存区,将缓冲区的字节全都刷新到文件上,再关闭流。

没有close方法,也就是没有进行刷新操作,文件有可能会变小。文件变小,说明了还有一部分内容没有完成写入到文件。前面一篇,我们介绍了缓冲区默认大小是8192字节,上面文件在最后一次写入到文件的缓冲区里,里面字节数没有8192大小,所以不会触发自动写入操作,从而留下一部分字节没有写入到文件。只要文件不是8192字节的N倍大小,如果最后不进行close操作,肯定会丢失一部分数据。

4.5.4、fulsh的使用

InputStream input =  httpconn.getInputStream();  
                  
ByteArrayOutputStream baos = new ByteArrayOutputStream();  
byte[] buffer = new byte[1024];  
int len;  
while ((len = input.read(buffer)) > -1 ) {  
    baos.write(buffer, 0, len);  
}  
baos.flush();                
  
InputStream stream1 = new ByteArrayInputStream(baos.toByteArray());  
  
//TODO:显示到前台  
  
InputStream stream2 = new ByteArrayInputStream(baos.toByteArray());  
  
//TODO:本地缓存  

工具类

1、SFTP

package com.healerjean.proj.util.file;

import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;

@Component
@Slf4j
public class SFTPUtil {

    private static final String encoding = "UTF-8";

    @Value("${sftp.host}")
    private String host;

    @Value("${sftp.port}")
    private String portStr;

    @Value("${sftp.username}")
    private String username;

    @Value("${sftp.password}")
    private String password;

    @Value("${sftp.remotePath}")
    private String remotePath;

    @Value("${sftp.rsa}")
    private String rsa;


    /**
     * 使用配置文件连接
     */
    private ChannelSftp connect() {
        ChannelSftp sftp = null;
        try {
            JSch jsch = new JSch();
            if (StringUtils.isNotBlank(rsa)) {
                jsch.addIdentity(rsa);
            }
            int port = Integer.valueOf(portStr);
            Session sshSession = jsch.getSession(username, host, port);
            log.info("Session created");
            if (StringUtils.isBlank(rsa)) {
                sshSession.setPassword(password);
            }
            Properties sshConfig = new Properties();
            sshConfig.put("StrictHostKeyChecking", "no");
            sshSession.setConfig(sshConfig);
            sshSession.connect();
            log.info("Session connected");
            log.info("Opening Channel");
            Channel channel = sshSession.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
            log.info("Connected to {}", host);
        } catch (Exception e) {
            log.info("Connected to {} failed", host, e);
            throw new RuntimeException(e.getMessage());
        }
        return sftp;
    }

    /**
     * 手动连接SFTP
     */
    private ChannelSftp handConnect(String rsa, String host, String portStr, String username, String password) {
        ChannelSftp sftp = null;
        try {
            JSch jsch = new JSch();
            if (StringUtils.isNotBlank(rsa)) {
                jsch.addIdentity(rsa);
            }
            int port = Integer.valueOf(portStr);
            Session sshSession = jsch.getSession(username, host, port);
            log.info("Session created");
            if (StringUtils.isBlank(rsa)) {
                sshSession.setPassword(password);
            }
            Properties sshConfig = new Properties();
            sshConfig.put("StrictHostKeyChecking", "no");
            sshSession.setConfig(sshConfig);
            sshSession.connect();
            log.info("Session connected");
            log.info("Opening Channel");
            Channel channel = sshSession.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
            log.info("Connected to {}", host);
        } catch (Exception e) {
            log.info("Connected to {} failed", host, e);
            throw new RuntimeException(e.getMessage());
        }
        return sftp;
    }

    /**
     * 断开连接
     */
    private void disconnect(ChannelSftp sftp) {
        if (sftp != null) {
            if (sftp.isConnected()) {
                sftp.disconnect();
                log.info("sftp is disconnecting");
            } else if (sftp.isClosed()) {
                log.info("sftp is already closed");
            }
            try {
                if (sftp.getSession().isConnected()) {
                    sftp.getSession().disconnect();
                }
            } catch (Exception e) {
                log.error("sftp  session is disconnect", e);
                throw new RuntimeException(e.getMessage());
            }
        }

    }


    /**
     * 去读Sfto文件
     *
     * @param directory      目录
     * @param remoteFileName 远程文件名
     * @return
     */
    public String readSFTPFile(String directory, String remoteFileName) {
        ChannelSftp sftp = connect();
        return readSFTPFile(remotePath + directory, remoteFileName, sftp);
    }

    /**
     * @param remoteDirectory 远程目录 比如 /asset/test
     * @param remoteFileName  远程文件名
     * @param sftp
     * @return
     */
    private String readSFTPFile(String remoteDirectory, String remoteFileName, ChannelSftp sftp) {
        if (sftp == null) {
            log.error("connect to sftp failed");
            return "false";
        }

        StringBuilder builder = new StringBuilder();
        BufferedReader reader = null;
        InputStream ins = null;

        try {
            sftp.cd(remoteDirectory);
            ins = sftp.get(remoteFileName);
            if (ins == null) {
                log.error("filename is not exit");
                return "";
            }
            reader = new BufferedReader(new InputStreamReader(ins, encoding));
            String inLine = reader.readLine();
            while (inLine != null) {
                builder.append(inLine);
                builder.append("\n");
                inLine = reader.readLine();
            }
        } catch (SftpException se) {
            log.info("read sftp {} error ", remoteFileName, se);
            throw new RuntimeException(se.getMessage());
        } catch (Exception e) {
            log.info("read sftp {} error ", remoteFileName, e);
            throw new RuntimeException(e.getMessage());
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (ins != null) {
                    ins.close();
                }
            } catch (IOException e) {
                log.error("read ftpFile close  InputStream or BufferedReader error ", e);
                throw new RuntimeException(e.getMessage());
            }
            disconnect(sftp);
        }
        return builder.toString();
    }


    /**
     * 下载单个文件到本地文件
     *
     * @param directory         远程目录
     * @param remoteFileName    远程文件名
     * @param downLoadLocalPath 本地下载后存储路径
     * @param localFileName     本地下载后的文件名
     * @return
     */
    public boolean downloadFile(String directory, String remoteFileName, String downLoadLocalPath, String localFileName) {
        ChannelSftp sftp = this.connect();
        return downloadFile(remotePath + directory, remoteFileName, downLoadLocalPath, localFileName, sftp);
    }

    /**
     * 下载单个文件到本地文件
     *
     * @param remoteDirectory   远程目录 比如 /asset/test
     * @param remoteFileName    远程文件名
     * @param downLoadLocalPath 本地下载后存储路径
     * @param localFileName     本地下载后的文件名
     * @return
     */
    private boolean downloadFile(String remoteDirectory, String remoteFileName, String downLoadLocalPath, String localFileName, ChannelSftp sftp) {
        FileOutputStream out = null;
        try {
            File file = new File(downLoadLocalPath, localFileName);
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            if (!file.exists()) {
                file.createNewFile();
            }
            out = new FileOutputStream(file);
            sftp.get(remoteDirectory + "/" + remoteFileName, out);
            log.info("down load single file success , {}", remoteFileName);
            return true;
        } catch (Exception e) {
            log.error("get file error", e);
            throw new RuntimeException(e.getMessage());
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    log.error("download single file close error", e);
                    throw new RuntimeException(e.getMessage());
                }
            }
            this.disconnect(sftp);
        }
    }


    /**
     * 批量下载文件
     *
     * @param remoteDirectory   远程下载的目录
     * @param downLoadLocalPath 下载的本地路径
     * @param fileStartFormat   文件名开头格式
     * @param del
     * @return
     */
    public boolean batchDownLoadFile(String remoteDirectory, String fileStartFormat, String downLoadLocalPath, boolean del, ChannelSftp sftp) {
        try {
            File directory = new File(downLoadLocalPath);
            if (!directory.exists()) {
                directory.mkdirs();
            }
            Vector v = listFiles(remoteDirectory, sftp);
            if (v.size() > 0) {
                log.info("batch down files start");
                Iterator iterator = v.iterator();
                while (iterator.hasNext()) {
                    ChannelSftp.LsEntry lsEntry = (ChannelSftp.LsEntry) iterator.next();
                    final String filename = lsEntry.getFilename();
                    SftpATTRS attrs = lsEntry.getAttrs();
                    //不是目录
                    if (!attrs.isDir()) {
                        //文件格式
                        if (StringUtils.isNotEmpty(fileStartFormat)) {
                            if (filename.startsWith(fileStartFormat)) {
                                if (downloadFile(remoteDirectory, filename, downLoadLocalPath, filename, sftp) && del) {
                                    deleteSFTPFile(remoteDirectory, filename, sftp);
                                }
                            }
                        } else {
                            if (downloadFile(remoteDirectory, filename, downLoadLocalPath, filename, sftp) && del) {
                                deleteSFTPFile(remoteDirectory, filename, sftp);
                            }
                        }
                    }
                }//while end
            }
        } catch (Exception e) {
            log.error("batch down files error", e);
            return false;
        } finally {
            this.disconnect(sftp);
        }
        return true;
    }


    /**
     * 批量下载文件
     *
     * @param directory         目录
     * @param downLoadLocalPath 下载的本地路径
     * @param fileStartFormat   文件名开头格式
     * @param del
     * @return
     */
    public boolean batchDownLoadFile(String directory, String fileStartFormat, String downLoadLocalPath, boolean del) {
        ChannelSftp sftp = this.connect();
        return batchDownLoadFile(remotePath, fileStartFormat, downLoadLocalPath, del, sftp);
    }


    /**
     * @param remoteDirectory 远程上传目录
     * @param uploadFileName  上传的文件名
     * @param inputStream     上传的流
     * @param sftp
     * @return
     */
    public boolean uploadFile(String remoteDirectory, String uploadFileName, InputStream inputStream, ChannelSftp sftp) {
        boolean flag = false;
        for (int i = 1; i < 3; i++) {
            log.info("开始第" + i + "次上传文件,名称 {}", uploadFileName);
            try {
                createDirAndCd(remoteDirectory, sftp);
                sftp.put(inputStream, uploadFileName);
                flag = true;
                log.info("第" + i + "次上传文件成功,名称 {}", uploadFileName);
                break;
            } catch (Exception e) {
                log.error("occurs exception", e);
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        log.error("occurs exception", e);
                    }
                }
                this.disconnect(sftp);
            }
            if (i == 3 && !flag) {
                log.info("上传3次均失败,文件名称 {}", uploadFileName);
            }
        }
        return flag;
    }


    /**
     * @param directory      目录
     * @param remoteFileName 上传的文件名
     * @param inputStream
     * @return
     */
    public boolean uploadFile(String directory, String remoteFileName, InputStream inputStream) {
        boolean flag = false;
        for (int i = 1; i < 4; i++) {
            log.info("开始第" + i + "次上传文件,名称 {}", remoteFileName);
            ChannelSftp sftp = this.connect();
            FileInputStream in = null;
            try {
                createDirAndCd(remotePath + "/" + directory, sftp);
                sftp.put(inputStream, remoteFileName);
                flag = true;
                log.info("第" + i + "次上传文件成功,名称 {}", remoteFileName);
                break;
            } catch (Exception e) {
                log.error("occurs exception", e);
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        log.error("occurs exception", e);
                    }
                }
                this.disconnect(sftp);
            }
            if (i == 3 && !flag) {
                log.info("上传3次均失败,商户 {},文件名称 {}", remoteFileName);
                // AlarmMailLog.logTask("上传3次均失败,商户 " + merchantId + ",文件 "+localFileName);
            }
        }//for 循环结束
        return flag;
    }


    /**
     * 创建目录 并切换到创建的目录下面
     */
    private boolean createDirAndCd(String createpath, ChannelSftp sftp) {
        try {
            if (isDirExist(createpath, sftp)) {
                sftp.cd(createpath);
                return true;
            }
            String pathArry[] = createpath.split("/");
            StringBuffer filePath = new StringBuffer("");
            for (String path : pathArry) {
                if (path.equals("")) {
                    continue;
                }
                filePath.append(path + "/");
                if (isDirExist(filePath.toString(), sftp)) {
                    sftp.cd(filePath.toString());
                    filePath.delete(0, filePath.length());
                } else {
                    // 建立目录
                    sftp.mkdir(filePath.toString());
                    // 进入并设置为当前目录
                    sftp.cd(filePath.toString());
                    filePath.delete(0, filePath.length());
                }
            }
            return true;
        } catch (SftpException e) {
            log.error("occurs exception", e);
        }
        return false;
    }


    private Vector listFiles(String remoteDirectory, ChannelSftp sftp) throws SftpException {
        return sftp.ls(remoteDirectory);
    }

    public Vector listFiles(String directory) {
        ChannelSftp sftp = this.connect();
        try {
            return listFiles(remotePath + directory, sftp);
        } catch (Exception e) {
            log.error("列举远程目录下文件出错", e);
            return null;
        } finally {
            this.disconnect(sftp);
        }
    }


    private void deleteSFTPFile(String directory, String deleteFile, ChannelSftp sftp) {
        try {
            sftp.cd(directory);
            sftp.rm(deleteFile);
            log.info("delete remote file success {}", deleteFile);
        } catch (Exception e) {
            log.error("delete remote file fail", e);
        }
    }

    /**
     * 判断目录是否存在
     */
    private boolean isDirExist(String directory, ChannelSftp sftp) {
        boolean isDirExistFlag = false;
        try {
            SftpATTRS sftpATTRS = sftp.lstat(directory);
            isDirExistFlag = true;
            return sftpATTRS.isDir();
        } catch (Exception e) {
            if (e.getMessage().toLowerCase().equals("no such file")) {
                isDirExistFlag = false;
            }
        }
        return isDirExistFlag;
    }


    /**
     * 测试
     * 1、连接Sftp
     * 2、读取sftp文件内容
     * 3、下载sftp文件
     * 4、上传文件
     * 5、批量下载文件
     */
    public static void main(String[] args) {
        SFTPUtil sftpUtil = new SFTPUtil();
        //1、连接Sftp
        ChannelSftp sftp = sftpUtil.handConnect("D:/work/sftp/id_rsa", "127.0.0.1", "22", "asset", null);

        //2、读取sftp文件内容
        //远程目录
        // String remoteDirectory = "/asset/test";
        //文件名
        // String remoteFileName = "check_info_result.txt";
        // String content = sftpUtil.readSFTPFile(remoteDirectory,remoteFileName,sftp);
        // System.out.println(content);

        // 3、下载sftp文件
        // String downLoadLocalPath = "D:/work/sftp/temp";
        // String downLoadFileName = "NEW.TXT" ;
        // sftpUtil.downloadFile(remoteDirectory,remoteFileName,downLoadLocalPath,downLoadFileName,sftp);


        // 4、上传文件
        // String uploadFileName = "upload_NEW.TXT";
        // try {
        //     FileInputStream inputStream = new FileInputStream("D:/work/sftp/temp/NEW.TXT");
        //     sftpUtil.uploadFile(remoteDirectory,uploadFileName,inputStream,sftp);
        // } catch (FileNotFoundException e) {
        //     e.printStackTrace();
        // }


        //5、批量下载文件
        // String downLoadLocalPath = "D:/work/sftp/temp";
        // sftpUtil.batchDownLoadFile(remoteDirectory,"u",downLoadLocalPath,false,sftp);

        //断开连接
        sftpUtil.disconnect(sftp);


    }
}

2、FTP

package com.healerjean.proj.util.file;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

import java.io.*;

@Slf4j
public class FtpUtil {

    private FTPClient ftpClient;

    public static void main(String[] args) throws Exception {
        FtpUtil t = new FtpUtil();
        t.connect("E:\resourse", "10.3.250.74", 21, "HealerJean", "147094");
        File file = new File("D:/test");
        t.upload(file);
    }


    /**
     * @param path     上传到ftp服务器哪个路径下
     * @param addr     地址
     * @param port     端口号
     * @param username 用户名
     * @param password 密码
     * @return
     * @throws Exception
     */
    private boolean connect(String path, String addr, int port, String username, String password) throws Exception {
        boolean result = false;
        ftpClient = new FTPClient();
        int reply;
        //连接ftp  默认是21 不写port也可以
        ftpClient.connect(addr, port);
        ftpClient.connect(addr);
        //ftp登录
        ftpClient.login(username, password);
        //文件类型为二进制文件
        ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
        reply = ftpClient.getReplyCode();
        //保存到ftp路径下
        if (!FTPReply.isPositiveCompletion(reply)) {
            ftpClient.disconnect();
            return result;
        }
        ftpClient.changeWorkingDirectory(path);
        result = true;

        return result;
    }


    /**
     * 关闭FTP连接
     */
    private void closeConnect() {
        if (ftpClient != null && ftpClient.isConnected()) {
            try {
                ftpClient.logout();
                ftpClient.disconnect();
            } catch (IOException e) {
                log.error("关闭FTP连接失败", e);
            }
        }
    }


    /**
     * 上传
     */
    private void upload(File file) throws Exception {
        if (file.isDirectory()) {
            ftpClient.makeDirectory(file.getName());
            ftpClient.changeWorkingDirectory(file.getName());
            String[] files = file.list();
            for (int i = 0; i < files.length; i++) {
                File file1 = new File(file.getPath() + "\\" + files[i]);
                if (file1.isDirectory()) {
                    upload(file1);
                    //上传目录
                    ftpClient.changeToParentDirectory();
                } else {
                    File file2 = new File(file.getPath() + "\\" + files[i]);
                    FileInputStream input = new FileInputStream(file2);
                    //上传文件
                    ftpClient.storeFile(file2.getName(), input);
                    input.close();
                }
            }
        } else {
            File file2 = new File(file.getPath());
            FileInputStream input = new FileInputStream(file2);
            //上传文件
            ftpClient.storeFile(file2.getName(), input);
            input.close();
        }
    }


    /**
     * 下载该目录下所有文件到本地
     * @param ftpPath  FTP服务器上的相对路径,例如:test/123
     * @param savePath 保存文件到本地的路径,例如:D:/test
     */
    public void downloadFiles(String ftpPath, String savePath) {
        // 登录
        if (ftpClient != null) {
            try {
                // 判断是否存在该目录
                if (!ftpClient.changeWorkingDirectory(ftpPath)) {
                    throw new RuntimeException("ftp目录不存在");
                }
                // 设置被动模式,开通一个端口来传输数据
                ftpClient.enterLocalPassiveMode();
                String[] listNames = ftpClient.listNames();
                // 判断该目录下是否有文件
                if (listNames == null || listNames.length == 0) {
                    throw new RuntimeException("ftp目录下文件不存在");
                }
                for (String fileNmae : listNames) {
                    File file = new File(savePath + '/' + fileNmae);
                    try (OutputStream os = new FileOutputStream(file)) {
                        ftpClient.retrieveFile(fileNmae, os);
                    } catch (Exception e) {
                        throw new RuntimeException("文件下载出错", e);
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException("文件下载出错", e);
            }
        }
    }


}

3、文件ContentType枚举

package com.hlj.util.Z017_文件ContentType;

/**
 * @author HealerJean
 * @ClassName FileEnum
 * @date 2019/11/7  19:58.
 * @Description
 */
public interface FileEnum {

    /**
     * 文件类型枚举
     */
    enum FileContentTypeEnum {

        doc(".doc","application/msword"),
        docx(".docx","application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
        xls(".xls","application/vnd.ms-excel"),
        xlsx(".xlsx","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
        csv(".csv","text/csv"),
        ppt(".ppt","application/vnd.ms-powerpoint"),


        ttf(".ttf","font/ttf"),
        js(".js","text/javascript"),
        css(".css","text/css"),
        xml(".xml","text/xml"),
        html(".html","text/html"),
        htm(".htm","text/html"),
        json(".json","application/json"),
        xhtml(".xhtml","application/xhtml+xml"),

        jpeg(".jpeg","image/jpeg"),
        jpg(".jpg","image/jpeg"),
        png(".png","image/png"),
        gif(".gif","image/gif"),
        ico(".ico","image/vnd.microsoft.icon"),
        tif(".tif","image/tiff"),
        tiff(".tiff","image/tiff"),

        jar(".jar","application/java-archive"),
        zip(".zip","application/zip"),
        tar(".tar","application/x-tar"),
        sh(".sh","application/x-sh"),

        mp3(".mp3","audio/mpeg"),


        ;
        private String code;
        private String mime;

        FileContentTypeEnum(String code, String mime) {
            this.code = code;
            this.mime = mime;
        }

        public String getCode() {
            return code;
        }
        public void setCode(String code) {
            this.code = code;
        }
        public String getMime() {
            return mime;
        }
        public void setMime(String mime) {
            this.mime = mime;
        }

        public static FileContentTypeEnum toEnum(String code) {
            for (FileContentTypeEnum item : FileContentTypeEnum.values()) {
                if (item.getCode().equals(code)) {
                    return item;
                }
            }
            return null;
        }
    }

}

问题

1、不使用递归遍历整个目录

  • 给定一个根目录,要求遍历其中的文件及子文件夹,返回所有后缀是.txt的文件List,不能使用递归
 * 作者 :HealerJean
 * 日期 :2019/3/13  下午2:34.
 * 类描述:给定一个根目录,要求遍历其中的文件及子文件夹,返回所有后缀是.txt的文件List
 * * 要求:
 * * 1. 不能使用递归
 */
public class Solution {

    @Test
    public void test() {
        File root = new File("/Users/healerjean/Desktop/faceFile");
        System.out.println(findTxt(root).toString());
    }

    /**
     * @param root 为一个文件夹根目录
     */
    public List<File> findTxt(File root) {
        List<File> listTxtFiles = new ArrayList<>();
        if (root.exists()) {
            //创建一个目录集合,用于存放跟目录下面的文件夹
            LinkedList<File> directorys = new LinkedList<>();
            //获取根目录下面的子目录文件夹(如果本目录下面包含txt文件,则直接加入listTxtFiles集合中)
            File[] files = root.listFiles();
            for (File file : files) {
                //判断是否为目录,然后
                if (file.isDirectory()) {
                    directorys.add(file);
                } else if (file.getName().endsWith(".txt")) {
                    listTxtFiles.add(new File(file.getAbsolutePath()));
                }
            }

            //创建一个临时目录,用于遍历directorys 集合中一个文件夹,如果是我们需要的txt文件,则直接加入集合中,如果该目录下包含子目录,则继续添加到directorys 集合中
            File temp_file;
            while (!directorys.isEmpty()) {
                //每次遍历directorys 中的第一个目录,遍历之前将它作废
                temp_file = directorys.removeFirst();
                files = temp_file.listFiles();
                for (File file : files) {
                    if (file.isDirectory()) {
                        directorys.add(file);
                    } else if (file.getName().endsWith(".txt")) {
                        listTxtFiles.add(new File(file.getAbsolutePath()));
                    }
                }
            }
        }
        return listTxtFiles;
    }

}

2、文件路径问题

2.1、Jar路径

String ttcp = this.class.getClassLoader().getResource(ttc).getPath();
    if (StringUtils.indexOf(ttcp, "jar!/") > 0) {
    ttcp = "jar:" + ttcp;
}

2.2、获取当前类所在包下位置的资源

String filePath = ClassGetResource.class.getResource("ClassGetResource.properties").getFile(); 

1573292314908

2.3、获取src或者resource下面的路径(到时候都是WEB-INF/classes下的文件)

String srcPath =  ClassLoader.class.getClassLoader().getResource("").getPath();

1573292405668

2.4、webroot目录

String srcPath = this.getServletContext().getRealPath("/WEB-INF/classes/NamePath.properties");

2.5、ClassPath其他方法

ClassPathResource resource = new ClassPathResource("cert/wechat/apiclient_cert.p12");
// 获取文件
File file = resource.getFile();
InputStream certinputStream = resource.getInputStream();

ResourceUtils.getFile("classpath:template");
Resource[] resources = ArrayUtils.addAll(
applicationContext.getResources("classpath*:com/admore/dao/mybatis/**/mysql/*.xml"),
applicationContext.getResources("classpath*:com/admore

3、InputStream对象的重复使用 以及fush正确写法


InputStream input =  httpconn.getInputStream();  
                  
ByteArrayOutputStream baos = new ByteArrayOutputStream();  
byte[] buffer = new byte[1024];  
int len;  
while ((len = input.read(buffer)) > -1 ) {  
    baos.write(buffer, 0, len);  
}  
baos.flush();                
  
InputStream stream1 = new ByteArrayInputStream(baos.toByteArray());  
  
//TODO:显示到前台  
  
InputStream stream2 = new ByteArrayInputStream(baos.toByteArray());  
  
//TODO:本地缓存  

感兴趣的,欢迎添加博主微信

哈,博主很乐意和各路好友交流,如果满意,请打赏博主任意金额,感兴趣的在微信转账的时候,备注您的微信或者其他联系方式。添加博主微信哦。

请下方留言吧。可与博主自由讨论哦

微信 微信公众号 支付宝
微信 微信公众号 支付宝
发布了311 篇原创文章 · 获赞 114 · 访问量 42万+

猜你喜欢

转载自blog.csdn.net/u012954706/article/details/102996778
今日推荐