1.文件的概念

  • 文件在程序中是以流的形式来操作的
  • JAVA程序中目录也被当做文件
  • new File只是在JAVA程序内存中创建了File对象,createNewFile才是真实的在硬盘中创建了文件数据

createNewFile方法内部的实现是依赖于Java平台本身对文件系统的底层操作,并不直接使用Java的流(Stream)API来创建文件。在Java中,流通常用于读取或写入数据,而createNewFile方法的目标是在文件系统上创建一个新的空文件,而不涉及到数据的读写

当调用createNewFile方法时,Java会向操作系统发送一个创建文件的请求。这一过程是通过Java的本地方法接口(JNI)或其他平台特定的机制实现的,以便直接利用操作系统提供的文件系统操作API。这意味着createNewFile的工作原理和性能特点与操作系统紧密相关,而与Java中的流处理(如FileInputStream, FileOutputStream, BufferedReader, BufferedWriter等)是分开的。

2.File类及其常用API


Java中的File类是java.io的一部分,它用于表示文件和目录路径名的抽象表示形式。通过使用File,你可以进行文件和目录的创建文件搜索删除文件或目录获取文件属性等操作。File不仅可以用于文件处理,还可以用于访问目录中的文件和目录列表

  • 获取文件的相关信息
  • exists(): 检查文件或目录是否存在。
  • getName(): 返回由此File表示的文件或目录的名称。
  • getAbsolutePath(): 返回此File的绝对路径名字符串。
  • isFile(): 检查由此File表示的对象是否是一个标准文件。
  • length(): 返回由此File表示的文件的长度。
  • list(): 返回一个字符串数组,这些字符串指定此File目录中的文件和目录。
  • renameTo(File dest): 将此File重命名为由参数dest指定的路径名
  • 目录的操作和文件删除
  • isDirectory(): 检查由此File表示的对象是否是一个目录。
  • mkdir(): 创建由此File表示的目录。
  • delete(): 删除由此File表示的文件或目录。

3.项目中用到File类做什么:使用File类一般也离不开使用FileInputStream

  • 执行SQL:在项目迁移或者不同的环境下,需要去动态地执行不同的sql脚本,这个时候就需要指定路径读取SQL文件内容,并使用JdbcTemplate执行,入参relativePath是指定的相对路径,也就是告诉该方法去哪里找这个sql文件。再用new File把该文件对象创建出来。再将该对象传入new FileInputStream中,如果没有报FileNotFoundException,就证明可以在对应的路径找到该文件。
@Override
	public void executeSql(String relativePath, JdbcTemplate jdbcTemplate) {

		//标识是否找到要执行的sql文件
		boolean exist = false;

		String sqlContent = null;

		InputStream inputStream = null;


		//先尝试在fat jar的home目录查找
		//执行方案的目录为 fat jar root path  + scheme
		String homePath = getHomePath();
		String sqlPath = homePath + "/" + relativePath;
		File file = new File(sqlPath);
		try {
			inputStream = new FileInputStream(file);
			exist = true;
			System.out.println(" 在 " + file + "中找到执行sql");
		} catch (FileNotFoundException e) {
			exist = false;
		}

		//如果不存在,尝试在resources下查找
		if (!exist) {

			try {
				Resource resource = new ClassPathResource(relativePath);
				inputStream = resource.getInputStream();
				System.out.println(" 在 resources/" + relativePath + "中找到执行sql");

				exist = true;
			} catch (IOException e) {
				e.printStackTrace();
				exist = false;
			}
		}

		//如果最终找不到抛出异常给上层
		if (!exist) {
			throw new ServiceException("000", "sql文件【" + relativePath + "】找不到");
		}
        #找到的SQL文件内容读入sqlContent字符串
		sqlContent = FileUtil.readStreamToString(inputStream);
        #将sqlContent按";\n"分割成多个SQL语句。这里假设SQL文件中的每条SQL语句都以分号加换行符结束。
		String[] sqlArray = sqlContent.split(";\n");


		for (String sql : sqlArray) {
			//跳过为空的sql
			if (StringUtil.isEmpty(sql)) {
				continue;
			}

			jdbcTemplate.execute(sql);
		}

	}
#这个方法适用于需要根据不同环境或应用版本动态加载和执行SQL脚本的场景,尤其适合于需要数据库迁移和版本控制的复杂应用部署环境。



/**
     * 将流转换成一个字符串
     *
     * @param stream 流
     * @return
     */
    public static String readStreamToString(InputStream stream) {
        StringBuffer fileContentsb = new StringBuffer();
        String fileContent = "";

        try {
            InputStreamReader read = new InputStreamReader(stream, "utf-8");
            BufferedReader reader = new BufferedReader(read);
            String line;
            while ((line = reader.readLine()) != null) {
                fileContentsb.append(line + "\n");
            }
            read.close();
            read = null;
            reader.close();
            read = null;
            fileContent = fileContentsb.toString();
        } catch (Exception ex) {
            fileContent = "";
        }
        return fileContent;
    }

`(line = reader.readLine()) != null`这行代码是在读取文本文件时常用的一种模式,用于逐行读取文件直到文件末尾。这里具体的含义和运作原理如下:

- `reader.readLine()`调用`BufferedReader`的`readLine()`方法来读取文件的下一行。如果文件还有未读取的内容,`readLine()`方法会返回读取到的那一行文本;如果达到文件末尾,`readLine()`方法会返回`null`。

- `line = reader.readLine()`这部分将`readLine()`方法返回的字符串(可能是文件中的一行文本或者`null`)赋值给变量`line`。

- `(line = reader.readLine()) != null`整个表达式的意思是,将`reader.readLine()`的返回值赋值给`line`,然后检查`line`是否不等于`null`。

- 这行代码通常用在`while`循环的条件部分,意味着“只要`readLine()`方法返回的不是`null`(即,只要没有到达文件末尾),就继续执行循环体内的操作”。换句话说,它会逐行读取整个文件,直到没有更多的行可以读取。

这种模式有效地利用了`readLine()`返回`null`这一行为,以此作为循环结束的标志,这样就可以在不知道文件具体行数的情况下,读取文件的所有行。