diff --git a/code/src/main/java/com/codeforces/commons/io/FileUtil.java b/code/src/main/java/com/codeforces/commons/io/FileUtil.java index e29c997..dea94cb 100644 --- a/code/src/main/java/com/codeforces/commons/io/FileUtil.java +++ b/code/src/main/java/com/codeforces/commons/io/FileUtil.java @@ -282,6 +282,27 @@ public static String readFile(File file) throws IOException { return Objects.requireNonNull(executeIoOperation(() -> UnsafeFileUtil.readFile(file))); } + /** + * Reads a file, limiting the number of lines read and cropping each line + * if its length exceeds the maximum. + *
+ * This implementation is efficient because it uses Files.lines() for
+ * lazy, buffered, line-by-line processing, avoiding loading the entire
+ * file into memory. The .limit() operation short-circuits reading,
+ * stopping disk access as soon as maxLineCount is reached.
+ *
+ * @param file File to be read.
+ * @param maxLineCount Maximum number of lines to read.
+ * @param maxLineLength Maximum length of each line to crop to.
+ * @return String containing file data in cropped form.
+ * @throws IOException if can't read file (e.g., file doesn't exist, is a directory, or permission issues).
+ */
+ @Nonnull
+ public static String readFileCropped(File file, int maxLineCount, int maxLineLength) throws IOException {
+ return Objects.requireNonNull(executeIoOperation(()
+ -> UnsafeFileUtil.readFileCropped(file, maxLineCount, maxLineLength)));
+ }
+
/**
* Writes new file into filesystem. Overwrite existing if exists.
* Creates parent directory if needed.
@@ -1049,7 +1070,7 @@ private static long parseSize(@Nonnull String size, @Nonnegative int lastCharInd
/**
* Set executable permission for file.
*
- * @param file File to set permission.
+ * @param file File to set permission.
* @param executable {@code true} to set executable permission.
*/
public static void setExecutable(@Nonnull File file, boolean executable) {
diff --git a/code/src/main/java/com/codeforces/commons/io/internal/UnsafeFileUtil.java b/code/src/main/java/com/codeforces/commons/io/internal/UnsafeFileUtil.java
index acabd29..5373f6f 100644
--- a/code/src/main/java/com/codeforces/commons/io/internal/UnsafeFileUtil.java
+++ b/code/src/main/java/com/codeforces/commons/io/internal/UnsafeFileUtil.java
@@ -6,6 +6,7 @@
import com.codeforces.commons.lang.ObjectUtil;
import com.codeforces.commons.math.RandomUtil;
import com.codeforces.commons.properties.internal.CommonsPropertiesUtil;
+import com.codeforces.commons.text.StringUtil;
import com.google.common.primitives.Ints;
import com.google.errorprone.annotations.MustBeClosed;
import de.schlichtherle.truezip.file.TFile;
@@ -32,6 +33,8 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static com.codeforces.commons.math.Math.max;
@@ -879,6 +882,54 @@ public static byte[] downloadFileAsByteArray(
return IoUtil.toByteArray(connection.getInputStream(), maxSize);
}
+ @Nonnull
+ public static String readFileCropped(File file, int maxLineCount, int maxLineLength) throws IOException {
+ if (maxLineCount <= 0) {
+ return "";
+ }
+
+ List