Tiny Text Editor (Simpler than vi) in Java
This is a complete tiny text editor in one Java file.
Quick Run (from repo root)
1cd Site/static/code/examples/java
2javac TinyTextEditor.java
3java TinyTextEditorIt keeps things intentionally simple:
- open or create a text file
- show lines with numbers
- append, edit, and delete lines
- save to disk
- warn on unsaved quit
Code (Single Public Class)
1import java.io.IOException;
2import java.nio.file.Files;
3import java.nio.file.Path;
4import java.util.ArrayList;
5import java.util.List;
6import java.util.Scanner;
7
8public class TinyTextEditor {
9 public static void main(String[] args) {
10 Scanner scanner = new Scanner(System.in);
11 System.out.print("File name (default notes.txt): ");
12 String fileName = scanner.nextLine().trim();
13 if (fileName.isEmpty()) {
14 fileName = "notes.txt";
15 }
16
17 EditorState editor = new EditorState(Path.of(fileName));
18 editor.load();
19
20 System.out.println("Commands: show, append, edit, delete, save, quit");
21
22 while (true) {
23 System.out.print("> ");
24 String command = scanner.nextLine().trim().toLowerCase();
25
26 switch (command) {
27 case "show":
28 editor.show();
29 break;
30 case "append":
31 System.out.print("Text: ");
32 editor.append(scanner.nextLine());
33 break;
34 case "edit":
35 System.out.print("Line number: ");
36 int editLine = parseLineNumber(scanner.nextLine());
37 if (editLine > 0) {
38 System.out.print("New text: ");
39 editor.edit(editLine, scanner.nextLine());
40 }
41 break;
42 case "delete":
43 System.out.print("Line number: ");
44 int deleteLine = parseLineNumber(scanner.nextLine());
45 if (deleteLine > 0) {
46 editor.delete(deleteLine);
47 }
48 break;
49 case "save":
50 editor.save();
51 break;
52 case "quit":
53 if (editor.isDirty()) {
54 System.out.print(
55 "Unsaved changes. Type quit! to force: "
56 );
57 String confirm = scanner.nextLine().trim();
58 if (!"quit!".equals(confirm)) {
59 break;
60 }
61 }
62 System.out.println("Bye.");
63 return;
64 default:
65 System.out.println("Use: show, append, edit, delete, save, quit");
66 }
67 }
68 }
69
70 private static int parseLineNumber(String raw) {
71 try {
72 return Integer.parseInt(raw.trim());
73 } catch (NumberFormatException e) {
74 System.out.println("Please enter a number.");
75 return -1;
76 }
77 }
78
79 private static class EditorState {
80 private final Path file;
81 private final List<String> lines = new ArrayList<>();
82 private boolean dirty = false;
83
84 private EditorState(Path file) {
85 this.file = file;
86 }
87
88 private void load() {
89 if (!Files.exists(file)) {
90 System.out.println("New file: " + file);
91 return;
92 }
93 try {
94 lines.addAll(Files.readAllLines(file));
95 System.out.println("Loaded " + lines.size() + " line(s).");
96 } catch (IOException e) {
97 System.out.println("Could not read file. Starting empty.");
98 }
99 }
100
101 private void show() {
102 if (lines.isEmpty()) {
103 System.out.println("(empty)");
104 return;
105 }
106 for (int i = 0; i < lines.size(); i++) {
107 System.out.printf("%3d | %s%n", i + 1, lines.get(i));
108 }
109 }
110
111 private void append(String text) {
112 lines.add(text);
113 dirty = true;
114 System.out.println("Appended line " + lines.size() + ".");
115 }
116
117 private void edit(int lineNumber, String newText) {
118 int index = lineNumber - 1;
119 if (index < 0 || index >= lines.size()) {
120 System.out.println("Line out of range.");
121 return;
122 }
123 lines.set(index, newText);
124 dirty = true;
125 System.out.println("Line updated.");
126 }
127
128 private void delete(int lineNumber) {
129 int index = lineNumber - 1;
130 if (index < 0 || index >= lines.size()) {
131 System.out.println("Line out of range.");
132 return;
133 }
134 lines.remove(index);
135 dirty = true;
136 System.out.println("Line deleted.");
137 }
138
139 private void save() {
140 try {
141 Files.write(file, lines);
142 dirty = false;
143 System.out.println("Saved to " + file + ".");
144 } catch (IOException e) {
145 System.out.println("Save failed.");
146 }
147 }
148
149 private boolean isDirty() {
150 return dirty;
151 }
152 }
153}Run It
1javac TinyTextEditor.java
2java TinyTextEditorWhy this works for beginners
- One public class and one nested state class keep things readable.
- The command loop is easy to trace.
- You still get real file editing and save safety.