在 java 中输出文本文件的 CaesarCipher 程序
CaesarCipher program that output a text file in java
我正在尝试构建一个接受文本文件的程序,应用 CaesarCipher 方法和 returns 以及输出文件。
import java.util.*;
import java.io.*;
class CaesarCipher
{
public static void main (String [] args) throws FileNotFoundException {
System.out.print("What is the input file name? ");
Scanner keyboard = new Scanner(System.in);
String fileName = keyboard.nextLine();
Scanner inputFile = new Scanner (new File (fileName));
String inputFileString = inputFile.toString();
System.out.print("What is the input file name? ");
int s = 4;
System.out.println("Text : " + inputFileString);
System.out.println("Shift : " + s);
System.out.println("Cipher: " + encrypt(inputFileString, s));
}
public static String encrypt(String inputFileString, int s) {
StringBuilder result = new StringBuilder();
for (int i=0; i< inputFileString.length(); i++) {
if (Character.isUpperCase(inputFileString.charAt(i))) {
char ch = (char)(((int)inputFileString.charAt(i) + s - 65) % 26 + 65);
result.append(ch);
}
else {
char ch = (char)(((int)inputFileString.charAt(i) + s - 97) % 26 + 97);
result.append(ch);
}
}
return result.toString();
}
}
我有两个问题:
1- 程序正在编译,但是当我 运行 它并输入文本文件名时,我得到这个错误:
What is the input file name? Text :
java.util.Scanner[delimiters=\p{javaWhitespace}+][position=0][match
valid=false][need input=false][source
closed=false][skipped=false][group separator=\,][decimal
separator=.][positive prefix=][negative prefix=\Q-\E][positive
suffix=][negative suffix=][NaN string=\Q�\E][infinity string=\Q∞\E]
2- 如何构建包含编码文本的新输出文件?
您现有的代码不会实际将输入文件读入String
。您可以使用多种方法来做到这一点,其中一种方法是 Files.readAllLines(Path)
,其中 returns 一个 List<String>
文件行。流式传输,并使用行分隔符收集它。喜欢,
String inputFileString = Files.readAllLines(new File(fileName).toPath()).stream()
.collect(Collectors.joining(System.lineSeparator()));
至于写入文件,请查看PrintStream(File)
构造函数。
它与 StringBuilder 一起工作
StringBuilder inputFileString = new StringBuilder();
while (inputFile.hasNext()) {
String x = inputFile.nextLine();
inputFileString.append(x);
}
完整回答您的问题:
- 您没有以正确的方式使用扫描仪。这是一个很好的答案,它显示了 how to convert an InputStream to a String 的几种方式。您唯一需要知道的是如何获得文件的 InputStream(检查下面的代码)。
作为旁注,您应该始终记住关闭您的资源。如果不再使用,请关闭您的 FileInputStream (more details here)。
File file = new File("your/file/path/file.ending");
try (FileInputStream fis = new FileInputStream(file)) {
// your code here
} catch (FileNotFoundException e){
e.printStackTrace();
}
- 创建内容并将内容写入文件也有多种可能性。看看:如何使用 Java 将字符串保存到文本文件?
总而言之,我创建了一个工作示例,使用稍微不同的方式来实施凯撒加密,并使用 Files.lines(...) to read the files content and Files.write(...) 将加密内容写入新文件:
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Scanner;
import java.util.stream.Stream;
public class CaesarCipher {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.print("What is the input file name? ");
Path filePath = Paths.get(scanner.nextLine());
System.out.print("What is the output file name? ");
Path encodedFilePath = Paths.get(scanner.nextLine());
System.out.print("Caesar cipher offset? ");
final int offset = Integer.parseInt(scanner.nextLine());
// Retrieve a a stream of the input file, where each line is mapped using the encrypt function
Stream<String> mappedFileStream = Files.lines(filePath).map(msg -> CaesarCipher.encrypt(msg, offset));
// Write encrypted content to a new file using our mapped stream as an iterable
Files.write(
encodedFilePath,
(Iterable<String>) mappedFileStream::iterator,
StandardCharsets.UTF_8,
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
// Decrypt the encoded file content and print it
Files.lines(encodedFilePath)
.map((fileLine) -> CaesarCipher.decrypt(fileLine, offset))
.forEach(System.out::println);
}
public static String encrypt(String msg, int offset) {
offset = offset % 26 + 26;
StringBuilder encoded = new StringBuilder(msg.length());
for (char i : msg.toCharArray()) {
if (Character.isLetter(i)) {
char base = Character.isUpperCase(i) ? 'A' : 'a';
encoded.append((char) (base + (i - base + offset) % 26));
} else {
encoded.append(i);
}
}
return encoded.toString();
}
public static String decrypt(String enc, int offset) {
return encrypt(enc, 26 - offset);
}
}
我正在尝试构建一个接受文本文件的程序,应用 CaesarCipher 方法和 returns 以及输出文件。
import java.util.*;
import java.io.*;
class CaesarCipher
{
public static void main (String [] args) throws FileNotFoundException {
System.out.print("What is the input file name? ");
Scanner keyboard = new Scanner(System.in);
String fileName = keyboard.nextLine();
Scanner inputFile = new Scanner (new File (fileName));
String inputFileString = inputFile.toString();
System.out.print("What is the input file name? ");
int s = 4;
System.out.println("Text : " + inputFileString);
System.out.println("Shift : " + s);
System.out.println("Cipher: " + encrypt(inputFileString, s));
}
public static String encrypt(String inputFileString, int s) {
StringBuilder result = new StringBuilder();
for (int i=0; i< inputFileString.length(); i++) {
if (Character.isUpperCase(inputFileString.charAt(i))) {
char ch = (char)(((int)inputFileString.charAt(i) + s - 65) % 26 + 65);
result.append(ch);
}
else {
char ch = (char)(((int)inputFileString.charAt(i) + s - 97) % 26 + 97);
result.append(ch);
}
}
return result.toString();
}
}
我有两个问题: 1- 程序正在编译,但是当我 运行 它并输入文本文件名时,我得到这个错误:
What is the input file name? Text : java.util.Scanner[delimiters=\p{javaWhitespace}+][position=0][match valid=false][need input=false][source closed=false][skipped=false][group separator=\,][decimal separator=.][positive prefix=][negative prefix=\Q-\E][positive suffix=][negative suffix=][NaN string=\Q�\E][infinity string=\Q∞\E]
2- 如何构建包含编码文本的新输出文件?
您现有的代码不会实际将输入文件读入String
。您可以使用多种方法来做到这一点,其中一种方法是 Files.readAllLines(Path)
,其中 returns 一个 List<String>
文件行。流式传输,并使用行分隔符收集它。喜欢,
String inputFileString = Files.readAllLines(new File(fileName).toPath()).stream()
.collect(Collectors.joining(System.lineSeparator()));
至于写入文件,请查看PrintStream(File)
构造函数。
它与 StringBuilder 一起工作
StringBuilder inputFileString = new StringBuilder();
while (inputFile.hasNext()) {
String x = inputFile.nextLine();
inputFileString.append(x);
}
完整回答您的问题:
- 您没有以正确的方式使用扫描仪。这是一个很好的答案,它显示了 how to convert an InputStream to a String 的几种方式。您唯一需要知道的是如何获得文件的 InputStream(检查下面的代码)。 作为旁注,您应该始终记住关闭您的资源。如果不再使用,请关闭您的 FileInputStream (more details here)。
File file = new File("your/file/path/file.ending");
try (FileInputStream fis = new FileInputStream(file)) {
// your code here
} catch (FileNotFoundException e){
e.printStackTrace();
}
- 创建内容并将内容写入文件也有多种可能性。看看:如何使用 Java 将字符串保存到文本文件?
总而言之,我创建了一个工作示例,使用稍微不同的方式来实施凯撒加密,并使用 Files.lines(...) to read the files content and Files.write(...) 将加密内容写入新文件:
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Scanner;
import java.util.stream.Stream;
public class CaesarCipher {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.print("What is the input file name? ");
Path filePath = Paths.get(scanner.nextLine());
System.out.print("What is the output file name? ");
Path encodedFilePath = Paths.get(scanner.nextLine());
System.out.print("Caesar cipher offset? ");
final int offset = Integer.parseInt(scanner.nextLine());
// Retrieve a a stream of the input file, where each line is mapped using the encrypt function
Stream<String> mappedFileStream = Files.lines(filePath).map(msg -> CaesarCipher.encrypt(msg, offset));
// Write encrypted content to a new file using our mapped stream as an iterable
Files.write(
encodedFilePath,
(Iterable<String>) mappedFileStream::iterator,
StandardCharsets.UTF_8,
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
// Decrypt the encoded file content and print it
Files.lines(encodedFilePath)
.map((fileLine) -> CaesarCipher.decrypt(fileLine, offset))
.forEach(System.out::println);
}
public static String encrypt(String msg, int offset) {
offset = offset % 26 + 26;
StringBuilder encoded = new StringBuilder(msg.length());
for (char i : msg.toCharArray()) {
if (Character.isLetter(i)) {
char base = Character.isUpperCase(i) ? 'A' : 'a';
encoded.append((char) (base + (i - base + offset) % 26));
} else {
encoded.append(i);
}
}
return encoded.toString();
}
public static String decrypt(String enc, int offset) {
return encrypt(enc, 26 - offset);
}
}