6666import org .apache .commons .io .function .IOTriFunction ;
6767import org .apache .commons .io .input .CharSequenceReader ;
6868import org .apache .commons .io .input .QueueInputStream ;
69+ import org .apache .commons .io .input .buffer .LineEndUnifiedBufferedReader ;
6970import org .apache .commons .io .output .AppendableWriter ;
7071import org .apache .commons .io .output .ByteArrayOutputStream ;
7172import org .apache .commons .io .output .NullOutputStream ;
@@ -1029,14 +1030,46 @@ private static boolean contentEquals(final Stream<?> stream1, final Stream<?> st
10291030 }
10301031
10311032 // TODO Consider making public
1032- private static boolean contentEqualsIgnoreEOL (final BufferedReader reader1 , final BufferedReader reader2 ) {
1033- if (reader1 == reader2 ) {
1034- return true ;
1035- }
1036- if (reader1 == null || reader2 == null ) {
1037- return false ;
1033+ private static boolean contentEqualsIgnoreEOL (
1034+ final LineEndUnifiedBufferedReader bufferedInput1 ,
1035+ final LineEndUnifiedBufferedReader bufferedInput2
1036+ ) throws UncheckedIOException {
1037+ /*
1038+ * We use this variable to mark if last char be '\n'.
1039+ * Because "a" and "a\n" is thought contentEqualsIgnoreEOL,
1040+ * but "\n" and "\n\n" is thought not contentEqualsIgnoreEOL.
1041+ */
1042+ boolean justNewLine = true ;
1043+
1044+ int currentChar1 ;
1045+ int currentChar2 ;
1046+
1047+ while (true ) {
1048+ currentChar1 = bufferedInput1 .peek ();
1049+ currentChar2 = bufferedInput2 .peek ();
1050+
1051+ if (currentChar1 == EOF ) {
1052+ if (currentChar2 == EOF ) {
1053+ return true ;
1054+ } else {
1055+ if (!justNewLine ) {
1056+ return inputOnlyHaveCRLForEOF (bufferedInput2 , currentChar2 );
1057+ }
1058+ return false ;
1059+ }
1060+ } else if (currentChar2 == EOF ) {
1061+ if (!justNewLine ) {
1062+ return inputOnlyHaveCRLForEOF (bufferedInput1 , currentChar1 );
1063+ }
1064+ return false ;
1065+ }
1066+ if (currentChar1 != currentChar2 ) {
1067+ return false ;
1068+ }
1069+ justNewLine = currentChar1 == '\n' ;
1070+ bufferedInput1 .eat ();
1071+ bufferedInput2 .eat ();
10381072 }
1039- return contentEquals (reader1 .lines (), reader2 .lines ());
10401073 }
10411074
10421075 /**
@@ -1062,7 +1095,54 @@ public static boolean contentEqualsIgnoreEOL(final Reader reader1, final Reader
10621095 if (reader1 == null || reader2 == null ) {
10631096 return false ;
10641097 }
1065- return contentEqualsIgnoreEOL (toBufferedReader (reader1 ), toBufferedReader (reader2 ));
1098+
1099+ final LineEndUnifiedBufferedReader bufferedInput1 ;
1100+ if (reader1 instanceof LineEndUnifiedBufferedReader ) {
1101+ bufferedInput1 = (LineEndUnifiedBufferedReader ) reader1 ;
1102+ } else {
1103+ bufferedInput1 = new LineEndUnifiedBufferedReader (reader1 );
1104+ }
1105+
1106+ final LineEndUnifiedBufferedReader bufferedInput2 ;
1107+ if (reader2 instanceof LineEndUnifiedBufferedReader ) {
1108+ bufferedInput2 = (LineEndUnifiedBufferedReader ) reader2 ;
1109+ } else {
1110+ bufferedInput2 = new LineEndUnifiedBufferedReader (reader2 );
1111+ }
1112+ return contentEqualsIgnoreEOL (bufferedInput1 , bufferedInput2 );
1113+ }
1114+
1115+ /**
1116+ * private function used only in contentEqualsIgnoreEOL.
1117+ * used in contentEqualsIgnoreEOL to detect whether a input only have CRLF or EOF.
1118+ * @param input input reader
1119+ * @param currentChar current peek char of input
1120+ * @return true/false
1121+ * @throws IOException by input.read(), not me.
1122+ * @see #contentEqualsIgnoreEOL(Reader, Reader)
1123+ */
1124+ private static boolean inputOnlyHaveCRLForEOF (LineEndUnifiedBufferedReader input , int currentChar ) throws UncheckedIOException {
1125+
1126+ /*
1127+ * logically there should be some code like
1128+ *
1129+ * if (char1 == EOF) {
1130+ * return true;
1131+ * }
1132+ *
1133+ * here.
1134+ *
1135+ * But actually, if this input's read() is EOF, then we will not invoke this function at all.
1136+ * So the check is deleted.
1137+ *
1138+ * You can go contentEqualsIgnoreEOL for details.
1139+ */
1140+
1141+ if (currentChar == '\n' ) {
1142+ input .eat ();
1143+ return input .read () == EOF ;
1144+ }
1145+ return false ;
10661146 }
10671147
10681148 /**
0 commit comments