1
介绍 Introduction
DSA-Assignment04
本次作业的分数为 14,最终的提交时间是:
10:00 周三 3 月 13 日
这次作业是关于优先级队列,外部归并排序,CSV 文件和对 CSV 文件的处理。
逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不 是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必 须像二进制数字那样被解读的数据。CSV 文件由任意数目的记录组成,记录间以某种换行符分隔;每条 记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有 完全相同的字段序列。通常都是纯文本文件。建议使用 WORDPAD 或是记事本(NOTE)来开启,再则 先另存新档后用 EXCEL 开启,也是方法之一。(参考:https://baike.baidu.com/item/CSV/10739)
2
虽然 CSV 文件中有许多选项和复杂性,但我们只关注它主要的核心内容。 评分 Marking
• 如果想得到满分,你必须完成实现以下备注的所有方法:
(//WRITE YOUR CODE HERE AND REPLACE THE RETURN STATEMENT
• 如果你上传最终文件可以运行并且可以通过初始测试,你会的到 1 分
• 我们尽可能多的写了相关测试,但是如果这些测试不能满足你编写时的便捷,你可以自己编写一些
测试从而帮助你完成。
• 如果您的提交结构不正确或无法编译,或崩溃,或进入无限循环,则不会获得任何分数。
剽窃 Plagiarism
3
剽窃是不可被容忍的,对任何同学都是不公平的,所以请自行完成作业,从而可以从 TA 那里得到 相应的分数。如果你的作业被查出是剽窃,那么将不给予你任何分数。
所有提交上来的作业会在全网中进行对比,防止从外界来源进行复制粘贴,对每一位学生都会进行 这样的行为。
当讲师最后检查出有抄袭时,会将你的证据转交给高级导师,高级导师将查看证据并应用处罚和警 告,或者如有必要,将其转发给大学。
• 关于剽窃的指导说明:https://www.cs.bham.ac.uk/internal/taught-students/plagiarism 1
4
• 复制是抄袭:https://www.cs.bham.ac.uk/internal/taught-students/copying
• 大学中关于剽窃的规定:https://intranet.birmingham.ac.uk/as/studentservices/ conduct/plagiaris-
m/index.aspx
学生会 Student Welfare
如果你即将错过截止日期,或者因为一些无法控制的原因而落下,请联系学生会。有些学生会因为 代表大学参加一些活动从而影响到你即使的提交作业,应该联系我们。学生会按照实际情况从而延期或 者取消你的作业,或者安排其他的方式来应对这些不利的情况。当你出现这些情况时请即使联系学生会。
5
• •
• •
细节 Details
CsvUtils.java 中有许多方法需要你去实现:
getStudentID() 和 getStudentName(): 只需将你的学生 ID 和学生姓名修改到相应的返回值 中。
splitSortCsv(…): 将 CSV 文件以随机顺序拆分为有序“运行”的集合(单个 CSV 文件已有序, 并且在它们之间具有原始 CSV 文件的所有行)。
mergePairCsv(…): 将两个有序运行组合成一个有序运行。
mergeListCsv(): 通过重复调用 mergePairCsv(…)将有序运行列表组合到单个有序运行中。
为了帮助你,在 CvsUtilsTest.java 中为您提供了一组测试,以及一个提供处理 CsvFormatter.java 中所需的 CSV 格式的方法的类。特别是,CvsUtils.java 中提供了一个示例方法 tcopyCsv(…),以 向您展示打开文件的适当示例,以便使用 CsvFormatter 类读取和写入以及读取和写入 CSV 文件。在 编写代码之前,请仔细阅读所有相关代码。
5.1 路径,文件和读写 Paths, Files, Reading and Writing
该作业需要创建,读取和写入文件。你的作业项目目录包含文件“data”。此文件包含一些您应在 开发和测试中使用的 CSV 文件。你只应该读取此目录中的文件并将文件写入此目录。你编写的唯一文 件的名称应以“temp_”开头。评分软件会在安全沙箱环境中运行您的代码,任何在此目录外读取或写 入或写入名称不以“temp_”开头的文件的尝试都将导致抛出异常并导致程序失败。
java.nio.file.Path 类表示要处理的完整和部分文件路径字符串。默认情况下,当程序启动时,它 会将你的项目目录作为其当前工作目录。因此,如果你要为需要阅读的文件指定相对路径名称,例如 “data/state-abbrevs.csv”,然后它将查找从项目目录开始的文件路径。您经常希望能够在数据文件
夹中创建新文件的路径:
• 给定目录的路径变量 dataDir,您可以使用dataDir.resolve(“temp_copy.csv”)构造一个由
String 文件名“temp_copy.csv”给出的文件的路径变量。
• 你还可以使用Paths.get(“data”)或Paths.get(“data”,“temp_copy.csv”)等调用从字符串 创建路径
2
• 您可以使用path.getFileName()获取文件的 String 名称(路径的最后一个组件)。这实际上返回 一个包含单个组件的路径,而Path 的 toString()方法会将其转换为字符串。
• 如果你知道文件的路径,并且想要在同一目录中创建新文件的路径,则可以使用: path.resolveSibling(“temp\_new\_file.java”)
• 您需要为输出文件生成不与输入文件名或任何其他输出文件名冲突的名称。要执行此操作,请从输 入文件名中选择输出文件名:如果输入文件名为“abc.csv”,则输出文件名为“temp_0000_abc.csv” ,其中数字部分可以为每个输出递增你需要的。如果在变量 formpath 中输入文件 Path,并且临 时文件号计数器在整数变量 tempNum 中,则可以通过以下方式完成:
Path tmpPath = fromPath.resolveSibling(
String.format(“temp_%05d_%s”,tempNum,fromPath.getFileName());
5.1.1 扫描器和打印 Scanner and PrintWriter
对于该作业,你应该使用 Scanner 类来读取 CSV 文件,使用 PrintWriter 类来编写它们。这可
确保正确处理所有 unicode 字符。
• 您可以使用以下命令在 Path 对象指定的文件上打开扫描器:
Scanner from = new Scanner(fromPath);
• PrintWriter 类当前不支持从 Path 对象打开文件,因此首先必须将 Path 对象转换为 File 对象: PrintWriter to = new PrintWriter(toPath.toFile()))
打开文件后,务必确保将其关闭:
• 不关闭它可能意味着如果你打开许多文件,你的程序可能会崩: 您可以同时打开多少个文件。虽然 这个限制很大,但可以达到极限。
• 不关闭打开的文件,会占用内存,浪费内存资源。
• 在某种情况下,如果你不关闭文件,可能最后某些文件无法写入,从而保存到磁盘的文件中。
。因此,你应该养成一直关闭文件的习惯。虽然你可以直接关闭它们,但是必须确保它们在你进行调用 以关闭它们之前即使发生异常也会关闭。您可以使用 try … catch …finally 构造来处理这个问题,但 是有一种更简单,更方便的方法:try-with-resources 构造:
try( Scanner from = new Scanner(fromPath);
PrintWriter to = new PrintWriter(toPath.toFile)))
{
//在这里做你的读取和写入 – 不要关闭 }
3
这种形式的尝试确保构造为“try”部分的每个资源都使用以下花括号打开,并在程序离开大括号时自动 关闭,无论该异常是由异常,返回还是仅仅完成大括号中的代码。请注意,try 部分中的代码是由分号分 隔的一系列赋值。你可以拥有任意数量如果你愿意。如果您愿意,您也可以嵌套它们:
try( Scanner from = new Scanner(fromPath) )
{
//从这里读取“from”
try( PrintWriter to = new PrintWriter(toPath.toFile()) ) {
//从“from”读取并在此处写入“to” }
//从这里读取“from” }
5.2
优先队列和比较器 Priority Queues and Comparators
PriorityQueue 是 Java 的 Priority Queue 数据结构的实现。要使用它,您需要使用 Comparator 对象,该对象告诉 PriorityQueue 如何比较放入其中的对象。CsvFormatter 类包含适用于此目的的 嵌套 CsvComparator 类。由于它嵌套在 CsvFormatter 中,因此您只能从 CsvFormatter 对象创 建 CsvComparator 对象,如下所示:
CsFormatter formatter = … //获取格式化程序对象
String columnName = “abbreviation”; // 用于比较CSV行的列标题 CsvFormatter.RowComparator comparator = formatter.new RowComparator(columName)
对于这项作业,您需要将 CSV 行放入其中。这些行实现为字符串数组,因此,根据上面创建的比较器, 您可以创建一个合适的新 PriorityQueue,如下所示:
PriorityQueue
5.3 测试阵列的平等性 Testing Arrays for Equality 不要尝试在字符串数组(即一行)上使用.equals 方法来检查数组是否长度相同并且具有相同的字符
串,这样看起来似乎是有效,出于好的效果,不太建议你这样做。最好的方法是使用:Arrays.equals()。 String[] row1 = … //获取CSV行
String[] row2 = … //获取CSV行
if(row1.equals(row2)) // 不要这么做,这不是一个很好的方法 …
if(Arrays.equals(row1, row2)) // 需要这么做,这个是个很好的方法 …
4
5.4 最后指令 Final Instructions
• 关于需要填写的代码部分,所需要做的已经在 Javadoc 里进行详细的备注。
• 你需要修改在 CsvUtils.java 中的方法 CsvUtils.getStudentId() 和 CsvUtils.getStudentName() 的返回值。(即你的学生 ID 和学生姓名)。
• 你不能修改 CsvUtils.java 中的任何变量,类名或者方法名。更不需要添加任何其他的变量,也不 需要修改 src 文件中的主要文件和任何其他文件。
• 如果你想要,可以在 CsvUtils.java 中添加额外的 Private 方法,但请注意,它们不是必需的,我 的解决方案不会这样做。
• 您可以(并且应该!)修改 CsvUtilsTest.java 文件,您可以根据需要添加任何其他测试文件。你 的测试文件仅供您自己使用,不需要提交。
• 你只需要提交 CsvUtils.java 文件,不需要提交其他任何文件,所以不需要对其他任何文件进行修 改,但是在你编写时你必须和其他文件一起使用,因为它们是属于一体的。
• 你不需要使用任何关于打印语句来输出,如果你想要一些调试输出,请使用 Log4j 的日志记录来 调用。
• 程序将在安全沙箱的环境内进行,所以你不能破坏安全沙箱环境下的任何代码,任何尝试和破坏都 有可能会将程序带入无限循环或者无法正常运行。
• 您的代码可能会读取项目目录的“data”子目录中的任何文件,并在那里创建和写入任何文件,只 要您使用的文件名以“temp_”开头即可。将用于评分程序的安全沙箱环境将导致程序失败,如果 它尝试读取或写入任何不符合此要求的文件。
• 完成代码编写完成后,请提交 CsvUtils.java
5