你好 ChatGPT, 帮我看下这段代码有什么问题?

点赞再看,动力无限。 微信搜「 程序猿阿朗 」。

本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多系列文章。

今天一个很简单的功能,触发了一个 BUG,处理后我想起了最近爆火的 ChatGPT,于是我尝试测试 ChatGPT 能否发现这个 BUG。这篇文章会先介绍功能代码,然后手动分析 BUG 原因;接着测试 ChatGPT 能否发现这个 BUG。

ChatGPT(图片来自 projectpro.io)

先说下结论,测试结束,ChatGPT 今后可能是我编程路上的好帮手。

前言

今天在测试一个准备上线的新功能时,里面有一段简单的函数,出现了一个 BUG。我先说一下这个函数的功能,看下你会怎么写。

功能描述

输入:一个文件夹路径。

输出:这个文件夹中的文件夹数量。

这是一个实现起来比较简单的函数,我顺手写了下面的代码:

String pathString = "/Users/darcy/";
File fileDir = new File(pathString);
if (!fileDir.exists() || !fileDir.isDirectory()) {throw new RuntimeException("xxx....");
}
String[] fileList = fileDir.list();
int count = 0;
for (String filePath : fileList) {if (new File(pathString + filePath).isDirectory()) {count++;}
}
System.out.println(count);

功能是实现了,但是很明显,代码比较繁琐,于是我又顺手优化了一下。

Path path = Paths.get("/Users/darcy/");
if (!Files.exists(path) || !Files.isDirectory(path)) {throw new RuntimeException("xxx....");
}
long dirCount = Files.list(path).filter(Files::isDirectory).count();
System.out.println(dirCount);

效果是一样的,因为使用了 JDK 7 引入的 Files 类,让代码简单了不少。

不过正是这段代码,触发了 BUG,我先卖个关子,你先看下 BUG 在什么地方。

问题分析

你看出问题了吗?改造后的代码运行少量次数的情况下,都是可以正常输出的。但是它有一个问题,就是 Files.list 返回的 Stream 流没有进行关闭,这就导致如果这段代码被频繁的调用,一段时间后将会因为打开的文件过多而报错,可以测试出这种异常情况。

问题复现

在循环中不断运行这段代码:

 while (true){Path path = Paths.get("/Users/darcy/");if (!Files.exists(path) || !Files.isDirectory(path)) {throw new RuntimeException("xxx....");}long dirCount = Files.list(path).filter(Files::isDirectory).count();System.out.println(dirCount);}

一段时间后控制台收到报错:Too many open files

Files list Too many open files

问题原因

报错的原因是因为每个进程可以打开的文件数量是有限制的,如果一直打开不进行关闭,在达到限制时会报出这个错误。

不妨让代码运行速度降低,然后监控下随着程序的运行,运行进程持有的文件数是否不断增加。

while (true){Path path = Paths.get("/Users/darcy/");if (!Files.exists(path) || !Files.isDirectory(path)) {throw new RuntimeException("xxx....");}long dirCount = Files.list(path).filter(Files::isDirectory).count();System.out.println(dirCount);Thread.sleep(1000);
}

下面是用到的命令。

## 查找进程 ID
➜  ~ jps -mlVv | grep testFileList
## 查看指定进程引用的文件数量
➜  ~ lsof -p 62248 | wc -l

从测试结果中可以看到随着程序的运行,进程持有的文件数量不断上升。

问题解决

原因已经知道了,既然 Files.list 返回的 Stream 流没有进行关闭,那么进行关闭就可以解决问题。

while (true){Path path = Paths.get("/Users/darcy/");if (!Files.exists(path) || !Files.isDirectory(path)) {throw new RuntimeException("xxx....");}// 方式1:手动关闭流// Stream<Path> pathStream = Files.list(path);// long dirCount = pathStream.filter(Files::isDirectory).count();// pathStream.close();// 方式2:使用 try resource 自动关闭流try (Stream<Path> pathStream = Files.list(path);){long dirCount = pathStream.filter(Files::isDirectory).count();System.out.println(dirCount);}Thread.sleep(1000);
}

再次运行后,引用的文件数量不再上涨,BUG 解决。

➜  ~ lsof -p 62879 | wc -l321
➜  ~ lsof -p 62879 | wc -l321
➜  ~ lsof -p 62879 | wc -l321
➜  ~ lsof -p 62879 | wc -l321
➜  ~ lsof -p 62879 | wc -l321
➜  ~ lsof -p 62879 | wc -l321

ChatGPT 分析

如果这段代码使用 ChatGPT 分析,它能发现问题吗?我先告诉你答案,它能发现,而且描述的很好,并且给出了修复建议。

ChatGPT 分析代码

我问:

下面这段 Java 代码有什么问题吗?

Path path = Paths.get("/Users/darcy/");
if (!Files.exists(path) || !Files.isDirectory(path)) {throw new RuntimeException("fileDir.isDirectory() error");
}
long dirCount = Files.list(path).filter(Files::isDirectory).count();
System.out.println(dirCount);

ChatGPT:

这段代码首先会检查 /Users/darcy/ 目录是否存在并且是一个目录,如果不是,则会抛出 RuntimeException。接着,它会计算 /Users/darcy/ 目录下的子目录数量并将其打印到控制台。

这段代码看起来没有语法错误,但是在运行时可能会抛出 IOException,因为对文件系统进行操作时可能会出现各种异常情况。特别是,如果指定的路径不存在,则会抛出 NoSuchFileException。因此,在代码中最好捕获可能发生的异常并进行处理,或者在方法签名中声明抛出异常以通知调用方。

此外,还需要注意的是,Files.list(path) 方法返回的是一个 Stream<Path> 对象,需要注意其资源释放问题,以避免潜在的资源泄漏问题。通常情况下,可以使用 try-with-resources 语句来自动关闭流,例如:

try (Stream<Path> stream = Files.list(path)) {long dirCount = stream.filter(Files::isDirectory).count();System.out.println(dirCount);
} catch (IOException e) {// 处理异常
}

下面是对话截图:

ChatGPT 分析代码

ChatGPT 实现功能

问:

帮我用 Java 写一串代码。 功能描述。

输入:一个文件夹路径。

输出:这个文件夹中的文件夹数量。

ChatGPT 回答:

以下是 Java 代码示例,用于计算指定文件夹路径下的文件夹数量:

import java.io.File;public class FolderCount {public static void main(String[] args) {String path = "path/to/folder"; // 替换成你的文件夹路径File folder = new File(path);int count = 0;if (folder.isDirectory()) {File[] files = folder.listFiles();for (File file : files) {if (file.isDirectory()) {count++;}}}System.out.println("该文件夹中的文件夹数量为:" + count);}
}

该程序首先接收一个文件夹路径作为输入,然后创建一个 File 对象来代表该文件夹。然后它遍历该文件夹中的所有文件,如果找到一个文件夹,则将计数器加一。最后,它输出计数器的值作为结果。

下面是对话截图:

ChatGPT 写代码

总结

在本文中,我们介绍了一个简单功能的 Java 代码 BUG,即未关闭 Files.list() 返回的流对象,导致程序运行时可能会打开过多的文件而出现异常。我们通过手动分析代码和测试,找出了问题所在,并提供了两种解决方案,一种是手动关闭流,另一种是使用 try-with-resources 自动关闭流。最后,我们还使用 ChatGPT 测试了是否可以用 AI 自动识别代码中存在的问题,结果表明 ChatGPT 可以帮助我们发现这类问题,为我们的编程工作提供了有力的支持。

上面这个总结,也是 ChatGPT 帮我写的,相对于 ChatGPT 能给出具体的代码,我更震惊于 ChatGPT 对于语义的理解,不仅能理解我的输入,还能对代码意思进行自然语言描述。今后你很可能分辨不出你所阅读的文章是人类写的,还是 ChatGPT 自动生成的。

附录:ChatGPT 写代码测试

以下测试结果都是 ChatGPT 的具体回答,我没有改动一个字符。

问1

帮我用 Java 写一段代码。
输入:一个时间字符串,这个时间信息包含年月日时分秒。 
处理:提取时间字符串中的月份 
输出:这个月份有多少天

ChatGPT 回答:

以下是一个示例Java代码,它接受一个时间字符串作为输入,并从中提取出月份并计算该月有多少天:

import java.time.*;
import java.time.format.DateTimeFormatter;public class MonthDays {public static void main(String[] args) {String dateString = "2023-02-14 12:34:56"; // 输入时间字符串DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");LocalDateTime dateTime = LocalDateTime.parse(dateString, formatter);int daysInMonth = YearMonth.from(dateTime).lengthOfMonth(); // 提取月份并计算该月有多少天System.out.println(daysInMonth); // 输出该月天数}
}

在这个示例中,我们使用了Java 8引入的java.time包来处理日期和时间。首先,我们将输入时间字符串解析为一个LocalDateTime对象。然后,我们从LocalDateTime对象中提取出年月,并使用YearMonth类的lengthOfMonth()方法计算该月份有多少天。最后,我们将该天数输出到控制台。

下面是测试截图:

问2

帮我用 Java 写一段代码。 
输入:一个时间字符串,这个时间信息包含年月日时分秒。 
输出:把这个时间字符串进行转换。获取这个时间当天的第三小时第一秒

ChatGPT 回答:

以下是用 Java 实现获取输入时间当天第三小时第一秒的代码示例:

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;public class Main {public static void main(String[] args) {String timeString = "2023-02-14 12:34:56"; // 代表输入的时间字符串DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");LocalDateTime dateTime = LocalDateTime.parse(timeString, formatter); // 解析时间字符串// 获取当天的3:00:01LocalDateTime targetDateTime = LocalDateTime.of(dateTime.toLocalDate(), LocalTime.of(3, 0, 1));System.out.println(targetDateTime);}
}

解释:

  1. 首先,定义一个代表输入时间的字符串 timeString
  2. 然后,使用 DateTimeFormatter 类创建一个日期时间格式化器,以便将时间字符串转换为 LocalDateTime 对象。此处使用的格式化器模式字符串为 "yyyy-MM-dd HH:mm:ss",其中:
  • yyyy 代表四位数的年份,例如 2023。
  • MM 代表两位数的月份,例如 02。
  • dd 代表两位数的日期,例如 14。
  • HH 代表两位数的小时数(24 小时制),例如 12。
  • mm 代表两位数的分钟数,例如 34。
  • ss 代表两位数的秒数,例如 56。
  1. 使用 LocalDateTime.parse() 方法将时间字符串解析为 LocalDateTime 对象。
  2. 接下来,使用 LocalDateTime.toLocalDate() 方法获取输入时间所在的日期,并使用 LocalTime.of() 方法创建一个 LocalTime 对象,代表目标时间当天的 3:00:01。
  3. 最后,使用 LocalDateTime.of() 方法将日期和时间组合成一个 LocalDateTime 对象,即获取了输入时间当天的第三小时第一秒。打印该对象即可。

注意:这里的代码示例假设输入时间字符串的格式是固定的。如果输入时间的格式可能会发生变化,需要根据实际情况调整格式化器模式字符串。

问3

帮我用 Java 写一段代码。 
输入:一个长度为10的全是小写字母的字符串 
处理1:把这个字符串按字母逆序 
处理2:把这个字符串第3,6,9位字母转换成大写  
处理3:截取字符串的前7位进行输出

ChatGPT 回答:

以下是用 Java 实现对输入字符串进行处理的代码示例:

public class Main {public static void main(String[] args) {String inputStr = "abcdefghij"; // 输入的字符串// 处理1:按字母逆序String reverseStr = new StringBuilder(inputStr).reverse().toString();// 处理2:第3,6,9位字母转换成大写StringBuilder resultStrBuilder = new StringBuilder(reverseStr);resultStrBuilder.setCharAt(2, Character.toUpperCase(reverseStr.charAt(2)));resultStrBuilder.setCharAt(5, Character.toUpperCase(reverseStr.charAt(5)));resultStrBuilder.setCharAt(8, Character.toUpperCase(reverseStr.charAt(8)));String resultStr = resultStrBuilder.toString();// 处理3:截取前7位进行输出String outputStr = resultStr.substring(0, 7);System.out.println(outputStr);}
}

解释:

  1. 首先,定义一个代表输入字符串的变量 inputStr
  2. 处理1:使用 StringBuilder 类的 reverse() 方法将字符串逆序,并使用 toString() 方法转换为普通字符串。将逆序后的字符串保存在 reverseStr 变量中。
  3. 处理2:使用 StringBuilder 类创建一个新的字符串构建器,将逆序后的字符串 reverseStr 作为初始字符串。
  • 使用 setCharAt() 方法将第3,6,9位字母转换成大写字母。
  • 注意:字符串下标从0开始,因此第3,6,9位分别对应下标2、5、8。
  1. 将处理后的字符串构建器转换为普通字符串,保存在 resultStr 变量中。
  2. 处理3:使用 substring() 方法从处理后的字符串 resultStr 中截取前7位,保存在 outputStr 变量中。
  3. 最后,使用 System.out.println() 方法输出 outputStr 变量的值。

<完>

文章持续更新,可以微信搜一搜「 程序猿阿朗 」或访问「程序猿阿朗博客 」第一时间阅读。本文 Github.com/niumoo/JavaNotes 已经收录,有很多系列文章,欢迎Star。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/26464.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mac更改桌面名称

前后对比 Mac桌面可以很方便的将我们繁多的任务进行分类&#xff0c;通过创建多个桌面将不同的应用聚焦。但是MacOS创建的桌面默认的只能是下面这种样式&#xff1a; 而作为DIY爱好者&#xff0c;想要修改成下面的样式&#xff0c;通过重命名的方式来区分不同的桌面所担任的职…

Mac电脑如何添加多个桌面?Mac多桌面创建使用技巧

电脑桌面上乱七八糟的程序、窗口是否影响你的心情呢&#xff1f;Mac多桌面可以轻松解决这一难题。那么Mac电脑如何添加多个桌面呢&#xff1f;这里小编为大家带来了Mac多桌面创建使用技巧&#xff0c;一起来看看吧&#xff01; 1.打开Mission Control(调度中心) 系统偏好设置-调…

linux xfce4桌面 仿mac os美化

系统&#xff1a;Xubuntu 18.04 Xubuntu 美化之后的样子 一、安装xfce4的主题和图标 下载主题&#xff0c;图标样式&#xff1a;http://xfce-look.org/ 将下载的主题&#xff0c;移动到桌面主题目录&#xff1a;/usr/share/themes 将下载的图标&#xff0c;移动到图标主题目…

MacBook远程桌面Windows使用Microsoft Remote Desktop for Mac_亲测使用

MacBook远程桌面Windows使用Microsoft Remote Desktop for Mac_亲测使用 像Windows上有自带的远程桌面连接软件.MacBook没有自带的远程连接Windows桌面的工具,需要安装软件来实现. 像远程桌面控制软件一般有 TeamViewer、向日葵远程控制, ToDesk, Microsoft Remote Desktop f…

Mac远程连接Windows桌面的软件推荐

有时候我们会需要远程连接其他电脑桌面&#xff0c;实现远程办公、远程帮助他人等目的。Windows电脑之间可以用Windows自带远程桌面&#xff0c;Mac电脑也有自带的远程桌面功能。 那么Windows和Mac之间需要进行远程桌面连接&#xff0c;有没有办法实现&#xff1f;答案是有的。…

硬核桌面美化,让Windows电脑像Mac一样充满高级感!

我们经常需要在电脑桌面放置一些文件&#xff0c;方便日常使用和操作&#xff0c;但是如果不好好整理的话&#xff0c;时间一久桌面就会变得很乱&#xff0c;既不美观&#xff0c;也不好找&#xff0c;特别是每天一开机对着一桌面的文件&#xff0c;这滋味简直无比难受。 可是…

mac电脑如何快速显示桌面及切换应用

使用mac电脑时&#xff0c;我们习惯打开很多应用&#xff0c;文档等等。如果打开应用非常多&#xff0c;需要操作桌面&#xff0c;却不知如何快速返回桌面和切换应用时&#xff0c;操作就非常不便了&#xff0c;下面简单介绍mac电脑系统如何快速显示桌面及切换应用&#xff1f;…

mac远程桌面Microsoft Remote Desktop for Mac - Mac-连接Windows远程桌面

好记星不如烂笔头&#xff0c;这里记录平时工作中用到的东西&#xff0c;不喜可以留言。 1&#xff1a;在mac电脑远程桌面可以使用&#xff0c;Microsoft 远程桌面 使用 Microsoft Remote Desktop 这个还是很老的版本&#xff1b; Microsoft Remote Desktop 10 已经在 Mac…

计算机辅助翻译与笔译的关系,机器翻译 vs 计算机辅助翻译:有什么区别?

“计算机辅助翻译”和“机器翻译”听起来很相似&#xff0c;很容易混淆。但两者之间存在着显著的差异&#xff0c;会导致截然不同的结果。 机器翻译:快捷便宜&#xff0c;但不准确 机器翻译是将文本输入计算机&#xff0c;通过计算机算法将文本自动翻译成另一种语言来完成的。也…

catti 三笔 计算机专业,catti三级笔译含金量高吗

catti三级笔译含金量是很高的&#xff0c;它是一项在全国实行的、统一的、面向全社会的翻译专业资格认证考试&#xff0c;是对参考人员口译或笔译方面双语互译能力与水平的评价与认定。 CATTI三级笔译翻译难度如何 1、CATTI考试分综合能力和笔译实务&#xff0c;要两个都过60分…

干货!学习笔译需要坚持的几件事

干货&#xff01;学习笔译需要坚持的几件事 对于每个学习笔译的小伙伴来说&#xff0c;或许都经历过这样的迷茫&#xff1a; 辛苦练习没效果&#xff1f; 翻译理论一脸懵&#xff1f; 翻译技巧无头绪&#xff1f; 2020CATTI的考试时间已经尘埃落定&#xff0c;上下半年的两…

笔译现在用计算机考试了吗,做笔译需要计算机技术很强吗

bochuangshua 新兵答主 05-29 TA获得超过969个赞 我是做笔译的&#xff0c;本科毕业于安徽师范大学计算机教育专业(2019年毕业)&#xff0c;说两句吧 笔译说白了就是将一种语言转化为另一种语言的信息处理的过程&#xff0c;这个过程中可能遇到各种陌生行业(财经、冶金、IT、医…

Latex常用数学符号输入方法

原文地址&#xff1a; Latex常用数学符号输入方法 问题1&#xff1a;字母上面的上标输入方法 问题2&#xff1a;小写希腊字母的输入方法 问题3&#xff1a;大写希腊字母的输入方法 问题4&#xff1a;二元关系符的表达方式 问题5&#xff1a;二元运算符的表达方式 问题6&#xf…

Latex数学符号对应表

Latex数学符号对应表 - 叮叮当当sunny - 博客园 目录 1. 希腊字母2. 运算符符号3. 关系符号4. 箭头符号5. 括号符号6. 其他符号7. MATLAB 回到顶部 1. 希腊字母 字母实现字母实现αα\alphaAA\Alphaββ\betaBB\Betaγγ\gammaΓΓ\Gammaδδ\deltaΔΔ\Deltaϵϵ\epsilon…

mathtype2023专门打数学符号的软件

mathtype是数学公式编辑器&#xff0c;与常见的文字处理软件及演示程序配合使用&#xff0c;能够在各种文档中加入复杂的数学公式及符号&#xff0c;可用在编辑数学的试卷、书籍、报刊、论文、幻灯演示等方面&#xff0c;mathtype2023版是编辑数学资料工具! 在这款软件中主要帮…

Typora数学公式符号

Typora数学公式符号

符号与数学公式

论文中出现的符号和字母应尤其含义解释&#xff0c;写出一个符号表以便读者查询。如图所示是一个符号表。 1.公式前的句子标点需要统一&#xff0c;例如&#xff1a;the objective function can be defined as follows, xxxx(你的公式)。上面as follows后面用的是逗号&#xff…

常用数学符号的 LaTeX 表示方法(附代码)

常用数学公式的 LaTeX 表示方法&#xff08;附代码&#xff09; 换行问题指数和下标平方根上/下划线、上/下括号向量箭头分数积分、求和、乘积矩阵其他常用符号 换行问题 使用$$会自动换行。使用$会使得公式嵌入文字在同一行。 我是一个$$a_{1}$$ 我是一个$b_{1}$我是一个 a …

CSDN打出各种数学符号和数学公式

目录 1、基本四则运算2、指数对数3、根号、省略号、向量4、大&#xff08;小&#xff09;于等于号5、特殊符号、希腊字母符号6、累加累乘7、矩阵8、更改公式中的颜色 我们在用CSDN打出各种数学符号和数学公式时&#xff0c;需要学习一些关于LaTex的语法&#xff0c;在此做一个记…

Latex常用数学符号

手画 如果本文中没有相应得希腊字母表示&#xff0c;想要希腊字母的 MarkDown代码&#xff0c;只需要在detexify 网站中的框框里用鼠标写出该字母&#xff0c;再选择对应的代码即可 如下图 常用latex数学符号 另外下面是一些自己用到零碎的表示 把下标放置在正下方 $\max \…