├── .gitignore ├── src ├── main │ ├── resources │ │ ├── goodHebrew.txt │ │ ├── goodEnglish.txt │ │ ├── badEnglish.txt │ │ ├── badHebrew.txt │ │ └── bigHebrew.txt │ └── java │ │ └── com │ │ └── paypal │ │ └── gibberishdetector │ │ ├── GibberishDetectorExtended.java │ │ ├── GibberishDetector.java │ │ └── GibberishDetectorFactory.java └── test │ └── java │ └── com │ └── paypal │ └── gibberishdetector │ ├── GibberishDetectorTestUtils.java │ ├── HebrewGibberishDetectorTest.java │ └── EnglishGibberishDetectorTest.java ├── LICENSE ├── README.md └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .project 3 | .classpath -------------------------------------------------------------------------------- /src/main/resources/goodHebrew.txt: -------------------------------------------------------------------------------- 1 | משפט כלשהו בעברית 2 | משהו נוסף לכתוב 3 | זה הכל בינתיים -------------------------------------------------------------------------------- /src/main/resources/goodEnglish.txt: -------------------------------------------------------------------------------- 1 | rob 2 | two models 3 | some long sentence, might suck? 4 | Project Gutenberg 5 | a b c -------------------------------------------------------------------------------- /src/main/resources/badEnglish.txt: -------------------------------------------------------------------------------- 1 | zxcvwerjasc 2 | nmnjcviburili,<> 3 | zxcvnadtruqe 4 | ertrjiloifdfyyoiu 5 | grty iuewdiivjh -------------------------------------------------------------------------------- /src/main/resources/badHebrew.txt: -------------------------------------------------------------------------------- 1 | כשדכדכג 2 | כשדגכדשגכ 3 | דכגרטח כחל כלכאולט 4 | ה שדכעטח חצאוטם 5 | עהכגנצכע דגאידרא דגיטטט 6 | השדגכהג תוםתםץךףכעחכצ -------------------------------------------------------------------------------- /src/main/java/com/paypal/gibberishdetector/GibberishDetectorExtended.java: -------------------------------------------------------------------------------- 1 | package com.paypal.gibberishdetector; 2 | 3 | import java.util.List; 4 | 5 | public class GibberishDetectorExtended extends GibberishDetector { 6 | 7 | public GibberishDetectorExtended(List trainingLinesList, List goodLinesList, List badLinesList,String alphabet) { 8 | super(trainingLinesList, goodLinesList, badLinesList, alphabet); 9 | } 10 | 11 | @Override 12 | protected double getThreshold(double minGood, double maxBad) { 13 | return minGood; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016, PayPal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/test/java/com/paypal/gibberishdetector/GibberishDetectorTestUtils.java: -------------------------------------------------------------------------------- 1 | package com.paypal.gibberishdetector; 2 | 3 | 4 | 5 | import java.util.Random; 6 | 7 | import com.paypal.gibberishdetector.GibberishDetector; 8 | 9 | 10 | public class GibberishDetectorTestUtils { 11 | 12 | private static final String WHITE_SPACE = " "; 13 | 14 | public static void randomGibberishTest(String alphabet, GibberishDetector gibberishDetector) { 15 | Random rand = new Random(); 16 | double correctTagging = 0d; 17 | double inCorrectTagging = 0d; 18 | for (int i = 0; i < 1000; i++) { 19 | int numOfWords = rand.nextInt(10) + 2; 20 | StringBuilder line = new StringBuilder(); 21 | for (int j = 0; j < numOfWords; j++) { 22 | for (int c = 0; c < rand.nextInt(10) + 3; c++) { 23 | line.append(alphabet.charAt(rand.nextInt(alphabet.length()-1))); 24 | } 25 | line.append(WHITE_SPACE); 26 | } 27 | if (gibberishDetector.isGibberish(line.toString().trim())) { 28 | correctTagging++; 29 | System.out.println("correct: " + line); 30 | } 31 | else { 32 | inCorrectTagging++; 33 | System.out.println("failed to tag correctly: " + line); 34 | } 35 | } 36 | System.out.println("correct tagging percentage: " + correctTagging/1000); 37 | System.out.println("incorrect tagging percentage: " + inCorrectTagging/1000); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/com/paypal/gibberishdetector/HebrewGibberishDetectorTest.java: -------------------------------------------------------------------------------- 1 | package com.paypal.gibberishdetector; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import com.paypal.gibberishdetector.GibberishDetector; 7 | import com.paypal.gibberishdetector.GibberishDetectorFactory; 8 | 9 | public class HebrewGibberishDetectorTest { 10 | 11 | private String[] goodHebrewSentences = {"שלום קוראים לי שיר", "היום שלישי היום, מחר יהיה יום רביעי", "שלומית בונה סוכה מוארת וירוקה"}; 12 | private String[] badHebrewSentences = {"גע גכידגעי דכעדכי רק", "רט כגעעיצכ עשדעש געיח", "יל חי ךחי חיהך חי אבסק סקסקב"}; 13 | private static final String alphabet = "אבגדהוזחטיכךלמםנןסעפףצץקרשת "; 14 | 15 | private static GibberishDetectorFactory factory = new GibberishDetectorFactory(GibberishDetector.class); 16 | private static GibberishDetector gibberishDetector = factory.createGibberishDetectorFromLocalFile("bigHebrew.txt", "goodHebrew.txt", "badHebrew.txt", alphabet); 17 | 18 | @Test 19 | public void gibberishDetectorGoodHebrewTest() { 20 | for (String line : goodHebrewSentences) { 21 | Assert.assertEquals(false, gibberishDetector.isGibberish(line)); 22 | } 23 | } 24 | 25 | @Test 26 | public void gibberishDetectorBadHebrewTest() { 27 | for (String line : badHebrewSentences) { 28 | Assert.assertEquals(true, gibberishDetector.isGibberish(line)); 29 | } 30 | } 31 | 32 | @Test 33 | public void randomGibberishTest() { 34 | GibberishDetectorTestUtils.randomGibberishTest(alphabet, gibberishDetector); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/paypal/gibberishdetector/EnglishGibberishDetectorTest.java: -------------------------------------------------------------------------------- 1 | package com.paypal.gibberishdetector; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import com.paypal.gibberishdetector.GibberishDetector; 7 | import com.paypal.gibberishdetector.GibberishDetectorExtended; 8 | import com.paypal.gibberishdetector.GibberishDetectorFactory; 9 | 10 | public class EnglishGibberishDetectorTest { 11 | 12 | private String[] goodEnglishSentences = {"my name is Shir", "hello world", "and you can tell everybody that this is your song"}; 13 | private String[] badEnglishSentences = {"2 chhsdfitoixcv", "fasdf asg ggd fhgkv", "qmdu poebc vuutkl jsupwre"}; 14 | private static final String alphabet = "abcdefghijklmnopqrstuvwxyz "; 15 | 16 | private static GibberishDetectorFactory factory = new GibberishDetectorFactory(GibberishDetectorExtended.class); 17 | 18 | private static GibberishDetector gibberishDetector = factory.createGibberishDetectorFromLocalFile("bigEnglish.txt", 19 | "goodEnglish.txt", "badEnglish.txt", alphabet); 20 | 21 | @Test 22 | public void gibberishDetectorGoodEnglishTest() { 23 | for (String line : goodEnglishSentences) { 24 | Assert.assertEquals(false, gibberishDetector.isGibberish(line)); 25 | } 26 | } 27 | 28 | @Test 29 | public void gibberishDetectorBadEnglishTest() { 30 | for (String line : badEnglishSentences) { 31 | Assert.assertEquals(true, gibberishDetector.isGibberish(line)); 32 | } 33 | } 34 | 35 | @Test 36 | public void randomGibberishTest() { 37 | GibberishDetectorTestUtils.randomGibberishTest(alphabet, gibberishDetector); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gibberish-Detector 2 | 3 | Based on Python gibberish detector written by Rob Renaud. Ported into Java by Shir Fiszman. 4 | 5 | You can find the original here: https://github.com/rrenaud/Gibberish-Detector 6 | 7 | This gibberish detector is not limmited to a certain language, and can be trained on files by the user's choice. 8 | 9 | # How to use this library? 10 | Use GibberishDetectorFactory in order to create a new instance of the gibberish detector. 11 | You should supply it the following inputs: 12 | - A big text file in the language of your choice for training. 13 | - A small text file with correct sentences. 14 | - A small text file with gibberish sentences. 15 | - A string containing the alphaBet of that language plus a space character. 16 | You can pass the files' data as lists of string, java file objects, paths of the files, or the names of local files. 17 | The factory instantiates a new GibberishDetector object that is trained by this input. 18 | Use the 'isGibberish' method in order to determine if a sentence is gibberish or not. 19 | 20 | If you wish to select your own heuristic for setting the thrshold to classify sentences, you can override the method 'getThreshold' 21 | and implement it yourself. The factory can create instances of detectors that extend GibberishDetector. 22 | 23 | # Content 24 | java files: 25 | - GibberishDetector - implements the gibberish detector algorythm used in the python open source gibberish detector. 26 | - GibberishDetectorExtended - an example of a detector the extends GibberishDetector and overrides the 'isGibberish' method. 27 | - GibberishDetectorFactory - the factory for creating an instance of a gibberish detector by the user's input. 28 | 29 | text files: 30 | - bigEnglish.txt, goodEnglish.txt, badEnglish.txt - text files used as inputs in the test for english gibberish detector. same files used 31 | in the python open source gibberish detector. 32 | - bigHebrew.txt, goodHebrew.txt, badHebrew.txt - text files used as inputs in the test for hebrew gibberish detector. 33 | 34 | tests: 35 | - EnglishGibbeirishDetectorTest - test for english gibberish detector. Demonstrates the usage of the factory with the GibberishDetectorExtended. 36 | - HebrewGibberishDetectorTest - test for hebrew gibberish detector. Demonstrates the usage of the factory on a language different than english. 37 | 38 | # License 39 | 40 | Gibberish-Detector-Java is available under the MIT License. See [LICENSE.txt](LICENSE.txt). 41 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.paypal.tools 5 | Gibberish-Detector 6 | 0.0.2 7 | Gibberish-Detector 8 | Java port of gibberish-detector 9 | https://github.com/paypal/Gibberish-Detector-Java 10 | 11 | 12 | 13 | MIT License 14 | http://www.opensource.org/licenses/mit-license.php 15 | repo 16 | 17 | 18 | 19 | 20 | PayPal Open Source 21 | https://paypal.github.io 22 | 23 | 24 | 25 | scm:git:git@github.com:paypal/Gibberish-Detector-Java.git 26 | scm:git:git@github.com:paypal/Gibberish-Detector-Java.git 27 | https://github.com/paypal/Gibberish-Detector-Java 28 | 29 | 30 | 31 | 32 | junit 33 | junit 34 | 4.12 35 | test 36 | 37 | 38 | 39 | 40 | 41 | sonatype-nexus-staging 42 | https://oss.sonatype.org/service/local/staging/deploy/maven2 43 | 44 | 45 | sonatype-nexus-snapshots 46 | https://oss.sonatype.org/content/repositories/snapshots 47 | 48 | 49 | 50 | 51 | 52 | Shir Fiszman 53 | PayPal 54 | 55 | 56 | Eyal Allweil 57 | PayPal 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | org.apache.maven.plugins 66 | maven-gpg-plugin 67 | 1.6 68 | 69 | 70 | sign-artifacts 71 | verify 72 | 73 | sign 74 | 75 | 76 | 77 | 78 | 79 | org.apache.maven.plugins 80 | maven-source-plugin 81 | 3.0.1 82 | 83 | 84 | attach-sources 85 | 86 | jar-no-fork 87 | 88 | 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-javadoc-plugin 94 | 3.0.1 95 | 96 | 97 | attach-javadocs 98 | 99 | jar 100 | 101 | 102 | 103 | 104 | 105 | org.apache.maven.plugins 106 | maven-compiler-plugin 107 | 108 | UTF-8 109 | 1.8 110 | 1.8 111 | 112 | 113 | 114 | org.sonatype.plugins 115 | nexus-staging-maven-plugin 116 | 1.6.7 117 | true 118 | 119 | ossrh 120 | https://oss.sonatype.org/ 121 | true 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | org.apache.maven.plugins 130 | maven-compiler-plugin 131 | 132 | 133 | org.apache.maven.plugins 134 | maven-source-plugin 135 | 136 | 137 | org.apache.maven.plugins 138 | maven-javadoc-plugin 139 | 140 | 141 | org.apache.maven.plugins 142 | maven-gpg-plugin 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /src/main/java/com/paypal/gibberishdetector/GibberishDetector.java: -------------------------------------------------------------------------------- 1 | package com.paypal.gibberishdetector; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Collections; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * gibberish detector used to train and classify sentences as gibberish or not. 12 | * @author sfiszman 13 | * 14 | */ 15 | public class GibberishDetector { 16 | 17 | private final Map alphabetPositionMap = new HashMap(); 18 | private static final int MIN_COUNT_VAL = 10; 19 | 20 | private final String alphabet; 21 | private double[][] logProbabilityMatrix = null; 22 | private double threshold = 0d; 23 | 24 | public GibberishDetector(List trainingLinesList, List goodLinesList, List badLinesList, String alphabet) { 25 | this.alphabet = alphabet; 26 | train(trainingLinesList, goodLinesList, badLinesList); 27 | } 28 | 29 | private void train(List trainingLinesList, List goodLinesList, List badLinesList) { 30 | initializePositionMap(); 31 | 32 | int[][] alphabetCouplesMatrix = getAlphaBetCouplesMatrix(trainingLinesList); 33 | logProbabilityMatrix = getLogProbabilityMatrix(alphabetCouplesMatrix); 34 | 35 | List goodProbability = getAvgTransitionProbability(goodLinesList, logProbabilityMatrix); 36 | List badProbability = getAvgTransitionProbability(badLinesList, logProbabilityMatrix); 37 | 38 | double minGood = Collections.min(goodProbability); 39 | double maxBad = Collections.max(badProbability); 40 | 41 | if (minGood <= maxBad) { 42 | throw new AssertionError("cannot create a threshold"); 43 | } 44 | threshold = getThreshold(minGood, maxBad); 45 | } 46 | 47 | // can be overridden for another threshold heuristic implementation 48 | protected double getThreshold(double minGood, double maxBad) { 49 | return (minGood + maxBad) / 2; 50 | } 51 | 52 | private void initializePositionMap() { 53 | char[] alphabetChars = alphabet.toCharArray(); 54 | for (int i = 0; i < alphabetChars.length; i++) { 55 | alphabetPositionMap.put(alphabetChars[i], i); 56 | } 57 | } 58 | 59 | private String normalize(String line) { 60 | StringBuilder normalizedLine = new StringBuilder(); 61 | for (char c: line.toLowerCase().toCharArray()) { 62 | normalizedLine.append(alphabet.contains(Character.toString(c)) ? c : ""); 63 | } 64 | return normalizedLine.toString(); 65 | } 66 | 67 | private List getNGram(int n, String line) { 68 | String filteredLine = normalize(line); 69 | List nGram = new ArrayList(); 70 | for (int start = 0; start < filteredLine.length() - n + 1; start++) { 71 | nGram.add(filteredLine.substring(start, start + n)); 72 | } 73 | return nGram; 74 | } 75 | 76 | private int[][] getAlphaBetCouplesMatrix(List trainingLinesList) { 77 | int[][] counts = createArray(alphabet.length()); 78 | for (String line : trainingLinesList) { 79 | List nGram = getNGram(2, line); 80 | for (String touple : nGram) { 81 | counts[alphabetPositionMap.get(touple.charAt(0))][alphabetPositionMap.get(touple.charAt(1))]++; 82 | } 83 | } 84 | return counts; 85 | } 86 | 87 | private double[][] getLogProbabilityMatrix(int[][] alphabetCouplesMatrix) { 88 | int alphabetLength = alphabet.length(); 89 | double[][] logProbabilityMatrix = new double[alphabetLength][alphabetLength]; 90 | for (int i = 0; i < alphabetCouplesMatrix.length; i++) { 91 | double sum = getSum(alphabetCouplesMatrix[i]); 92 | for (int j = 0; j < alphabetCouplesMatrix[i].length; j++) { 93 | logProbabilityMatrix[i][j] = Math.log(alphabetCouplesMatrix[i][j]/sum); 94 | } 95 | } 96 | return logProbabilityMatrix; 97 | } 98 | 99 | private List getAvgTransitionProbability(List lines, double[][] logProbabilityMatrix) { 100 | List result = new ArrayList(); 101 | for (String line : lines) { 102 | result.add(getAvgTransitionProbability(line, logProbabilityMatrix)); 103 | } 104 | return result; 105 | } 106 | 107 | private double getAvgTransitionProbability(String line, double[][] logProbabilityMatrix) { 108 | double logProb = 0d; 109 | int transitionCount = 0; 110 | List nGram = getNGram(2, line); 111 | for (String touple : nGram) { 112 | logProb += logProbabilityMatrix[alphabetPositionMap.get(touple.charAt(0))][alphabetPositionMap.get(touple.charAt(1))]; 113 | transitionCount++; 114 | } 115 | return Math.exp(logProb / Math.max(transitionCount, 1)); 116 | } 117 | 118 | private int[][] createArray(int length){ 119 | int[][] counts = new int[length][length]; 120 | for (int i = 0; i < counts.length; i++){ 121 | Arrays.fill(counts[i], MIN_COUNT_VAL); 122 | } 123 | return counts; 124 | } 125 | 126 | private double getSum(int[] array) { 127 | double sum = 0; 128 | for (int i = 0; i < array.length; i++) { 129 | sum += array[i]; 130 | } 131 | return sum; 132 | } 133 | 134 | /** 135 | * determines if a sentence is gibberish or not. 136 | * @param line a sentence to be classified as gibberish or not. 137 | * @return true if the sentence is gibberish, false otherwise. 138 | */ 139 | public boolean isGibberish(String line) { 140 | return !(getAvgTransitionProbability(line, logProbabilityMatrix) > threshold); 141 | } 142 | } -------------------------------------------------------------------------------- /src/main/java/com/paypal/gibberishdetector/GibberishDetectorFactory.java: -------------------------------------------------------------------------------- 1 | package com.paypal.gibberishdetector; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileReader; 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | import java.nio.charset.Charset; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * gibberish detector factory for creating an instance of GibberishDetector or another detector that extends it. 14 | * @author sfiszman 15 | * 16 | */ 17 | public class GibberishDetectorFactory { 18 | 19 | private Class type; 20 | 21 | public GibberishDetectorFactory(Class type) { 22 | this.type = type; 23 | } 24 | /** 25 | * creates a gibberish detector trained by the given lines and alphabet. 26 | * @param trainingList list of lines for training 27 | * @param goodList list of good valid lines 28 | * @param badList list of bad gibberish lines 29 | * @param alphabet String that contains all the alphabet of the language plus the white space character. for example: "abcdefghijklmnopqrstuvwxyz " 30 | * @return gibberish detector 31 | */ 32 | public GibberishDetector createGibberishDetector(List trainingList, List goodList, List badList, String alphabet) { 33 | try { 34 | return type.getConstructor(new Class[] {List.class, List.class, List.class, String.class}).newInstance(trainingList, goodList, badList, alphabet); 35 | } 36 | catch (Exception e) { 37 | throw new IllegalArgumentException("Exception in GibberishDetectorFactory: " + (e.getCause() != null ? e.getCause().getMessage() : "")); 38 | } 39 | } 40 | 41 | /** 42 | * creates a gibberish detector trained by the given Files and alphabet. 43 | * @param trainingFile file object that contains lines for training 44 | * @param goodFile file object that contains good valid lines 45 | * @param badFile file object that contains bad gibberish lines 46 | * @param alphabet String that contains all the alphabet of the language plus the white space character. for example: "abcdefghijklmnopqrstuvwxyz " 47 | * @return gibberish detector 48 | */ 49 | public GibberishDetector createGibberishDetector(File trainingFile, File goodFile, File badFile, String alphabet) { 50 | try { 51 | return createGibberishDetector(getLinesFromFile(trainingFile), getLinesFromFile(goodFile), getLinesFromFile(badFile), alphabet); 52 | } 53 | catch (IllegalArgumentException e) { 54 | throw new IllegalArgumentException(e.getMessage()); 55 | } 56 | catch (RuntimeException e) { 57 | throw new RuntimeException("Exception in GibberishDetectorFactory: " + e.getMessage()); 58 | } 59 | } 60 | 61 | /** 62 | * creates a gibberish detector trained by the given file paths and alphabet. 63 | * @param trainingFilePath path of a file that contains lines for training 64 | * @param goodFilePath path of a file that contains good valid lines 65 | * @param badFilePath path of a file that contains bad gibberish lines 66 | * @param alphabet String that contains all the alphabet of the language plus the white space character. for example: "abcdefghijklmnopqrstuvwxyz " 67 | * @return gibberish detector 68 | */ 69 | public GibberishDetector createGibberishDetector(String trainingFilePath, String goodFilePath, String badFilePath, String alphabet) { 70 | try { 71 | return createGibberishDetector(new File(trainingFilePath), new File(goodFilePath), new File(badFilePath), alphabet); 72 | } 73 | catch (IllegalArgumentException e) { 74 | throw new IllegalArgumentException(e.getMessage()); 75 | } 76 | catch (RuntimeException e) { 77 | throw new RuntimeException(e.getMessage()); 78 | } 79 | } 80 | 81 | /** 82 | * creates a gibberish detector trained by the given files names and alphabet. Assumes UTF-8 encoding. 83 | * @param trainingFileName name of a local file that contains lines for training 84 | * @param goodFileName name of a local file that contains good valid lines 85 | * @param badFileName name of a local file that contains bad gibberish lines 86 | * @param alphabet String that contains all the alphabet of the language plus the white space character. for example: "abcdefghijklmnopqrstuvwxyz " 87 | * @return gibberish detector 88 | */ 89 | public GibberishDetector createGibberishDetectorFromLocalFile(String trainingFileName, String goodFileName, String badFileName, String alphabet) { 90 | try { 91 | return createGibberishDetector(getLinesFromLocalFile(trainingFileName), getLinesFromLocalFile(goodFileName), getLinesFromLocalFile(badFileName), alphabet); 92 | } 93 | catch (IllegalArgumentException e) { 94 | throw new IllegalArgumentException(e.getMessage()); 95 | } 96 | catch (RuntimeException e) { 97 | throw new RuntimeException("Exception in GibberishDetectorFactory: " + e.getMessage()); 98 | } 99 | } 100 | 101 | private static List getLinesFromFile(File file) { 102 | List lines = new ArrayList(); 103 | 104 | try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) { 105 | String line; 106 | while ((line = bufferedReader.readLine()) != null) { 107 | lines.add(line.trim()); 108 | } 109 | } 110 | catch (IOException | NullPointerException e) { 111 | throw new RuntimeException("Can not initiate file: " + file.getAbsolutePath() , e); 112 | } 113 | return lines; 114 | } 115 | 116 | private static List getLinesFromLocalFile(String fileName) { 117 | List lines = new ArrayList(); 118 | 119 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName), Charset.forName("UTF-8")))){ 120 | while(reader.ready()) { 121 | lines.add(reader.readLine().trim()); 122 | } 123 | } catch (IOException | NullPointerException e) { 124 | throw new RuntimeException("Can not initiate file: " + fileName , e); 125 | } 126 | return lines; 127 | } 128 | } -------------------------------------------------------------------------------- /src/main/resources/bigHebrew.txt: -------------------------------------------------------------------------------- 1 | השם עֵבֶר מופיע במקרא כשמו של אחד מאבותיו של אברהם אבינו. המושג "עברי" נזכר במקרא פעמים רבות ככינוי לבני ישראל, אולם שמה של שפתם של העברים מכונה במקרא "יהודית",[3] וגם בשם "שפת כנען".[4] ייתכן שהשם 'יהודית' היה רק שם הניב שדובר בממלכת יהודה או באזור ירושלים, להבדיל מהניב של ממלכת הצפון, ממלכת ישראל. 2 | 3 | המקור הקדום ביותר המזכיר את המונח עברית כשם השפה, הוא מקור יווני מן המאה ה-2 לפנה"ס. המקור הוא נכדו של בן סירא שכותב בהקדמה לתרגום החיבור של סבו ליוונית שבוצע על ידו כי: 4 | 5 | לכן מתבקשים אתם לקרא את הקריאה ברצון ובתשומת לב, ולסלוח אם נראה שלא הצלחנו במילים ידועות שעמלנו באהבה לתרגם אותן 6 | כי הנאמרים בעברית (במקור בְּרַאִיסְטִי) אין כחם שווה כשהם מועתקים ללשון אחרת. 7 | – משה צבי סגל, ספר בן סירא השלם, עמ' א. לנוסח המקור ביוונית ראו כאן 8 | בלשון חז"ל שדוברה החל מהמאה הראשונה לספירה, הכינוי המקובל לשפה המקראית ולשפה המדוברת היה "לשון הקודש", והמונח "עברית" שימש לציון הכתב העברי הקדום, וכן לציון שפתם של בני עבר הנהר, אך יש גם שימושים במונח "עברית" המתייחסים ללשון המקרא 9 | 10 | כיום מכנים את הניב התנ"כי "לשון המקרא", כדי להבדילו מלשון חז"ל המכונה גם "לשון חכמים", שהיא בעצם ניב מאוחר של עברית. 11 | 12 | בברית החדשה משמש המונח "עברית" כשם לשפה הארמית שדוברה על ידי ה"עבריים" (תושבי עבר הנהר) בארץ ישראל, אולם בספרות חז"ל משמש מונח זה רק לעברית (המשנאית). 13 | 14 | עברית היא שפה המשתייכת לקבוצת הלשונות השמיות הצפון-מערביות, ומהווה את הדיאלקט בו דיברו תושבי ארץ ישראל החל מן האלף ה-2 לפנה"ס בלב האזור המכונה במקרא בשם ארץ כנען. כנען או הלבנט כולל היום את שטחיהן של לבנון, סוריה, ארץ ישראל וירדן. השפה הפיניקית אשר הייתה מדוברת באזור לבנון של ימינו היא "שפה אחות" לשפה העברית. טקסטים בני התקופה אשר התגלו בירדן ובלבנון חושפים קרבה רבה בין השפה העברית לשפה הפיניקית והמואבית. 15 | 16 | בעברית נכתבו רוב ספרי התנ"ך, כל המשנה, רוב הספרים החיצוניים ורוב המגילות הגנוזות. המקרא נכתב בעברית מקראית, ואילו המשנה נכתבה בניב הקרוי לשון חז"ל. בתקופה מסוימת בסוף המאה ה-2 לספירה או קצת מאוחר יותר (החוקרים חלוקים בשאלה זו) פסקו רוב היהודים מלהשתמש בעברית כבשפת דיבור. מאות שנים לאחר חתימת המשנה כאשר חדלו היהודים להשתמש בעברית כבר נכתבו התלמודים בארמית. עם זאת, ישנן עדויות שאף במאה ה-8 לספירה הייתה שפת הדיבור בטבריה, שם פעלו בעלי המסורה, עברית. 17 | 18 | גם כשהשפה העברית לא שימשה שפת דיבור, עדיין שימשה לאורך הדורות, במה שמכונה תקופת הביניים של העברית, כשפת הכתב העיקרית של היהודים, בעיקר בעניינים הלכתיים: כתיבת פרוטוקולים של בתי דין, קובצי הלכות, פרשנות לכתבי קודש ועוד. גם כתיבת מכתבים וחוזים בין גברים יהודים נעשתה לעתים קרובות בעברית. ספרות הלכתית לנשים בקהילות אשכנזיות נכתבה ביידיש (למשל ספר ההלכות "צאינה וראינה"), כיוון שהנשים, בניגוד לגברים, לא למדו עברית. חיבורים יהודיים בעלי אופי חילוני או לא-הלכתי נכתבו בשפות יהודיות או בשפות זרות, לדוגמה: הרמב"ם כתב את ספרו "משנה תורה" בעברית, על אף שספרו הפילוסופי המפורסם "מורה נבוכים", שיועד למשכילי זמנו, נכתב בערבית יהודית. עם זאת, "מורה נבוכים", כמו ספרים אחרים בנושאים חילוניים, תורגמו לעברית כשהיה בהם עניין לקהילות יהודיות דוברות שפות אחרות. אחת המשפחות היהודיות המפורסמות שעסקו בתרגום מערבית-יהודית לעברית בימי הביניים היא משפחת אִבְּן תִּיבּוֹן. 19 | 20 | עד המאה ה-19, ראשית ימי התנועה הציונית, שימשה העברית כשפת כתב בעיקר למטרות דתיות, אבל גם למטרות שונות ומגוונות: פילוסופיה, ספרות, מדע ורפואה. מעמדה בקרב היהודים היה דומה למעמדה של השפה הלטינית בקרב הנוצרים במערב אירופה. מסוף המאה ה-18, עם צמיחת תנועת ההשכלה היהודית בגרמניה ובמזרח אירופה, נכנסה השפה העברית לתנופה מודרנית. לאורך כל המאה ה-19 הלך השימוש החילוני בה וגבר. בד בבד עם תנועת התחייה הלאומית החלה גם פעילות להפיכת העברית ללשון הדיבור של היישוב העברי בארץ ישראל. אליעזר בן יהודה, המכונה "מחיה השפה העברית" היה בין הלוחמים למען הפיכת השפה העברית לשפה מדוברת ולשפתו הלאומית של היישוב העברי בארץ. במקביל התפתחה עברית מדוברת גם במרכזים אחדים של יהודים במזרח אירופה. המעבר לדיבור בעברית ביישוב העברי בארץ היה מהיר יחסית, וניכרה בו דווקא השפעת הדיבור העברי של מזרח אירופה. עם כינון שלטון המנדט הבריטי בארץ נקבעה העברית כשפה רשמית שלישית, לצד הערבית והאנגלית. ערב הקמת מדינת ישראל הייתה העברית כבר לשפה העיקרית של היישוב העברי, ושפת הלימוד במרכזי החינוך שלו. 21 | 22 | כיום יש כ-9 מיליון דוברי עברית ישראלית, רובם המכריע גרים בישראל. כ-5,300,000 (2009) דוברים ילידיים (כלומר, עברית היא שפת-אמם) והשאר משתמשים בעברית כשפה שנייה. עברית היא כיום השפה הרשמית והעיקרית של מדינת ישראל, אם כי בנוסף לה יש מעמד רשמי גם לשפה הערבית, וכן נעשה שימוש נרחב באנגלית, ברוסית ובשפות נוספות. בעקבות המסורת האירופית, שמקורה בהקמת האקדמיה הצרפתית, קיים גם בישראל גוף רשמי המכתיב תקנים של השפה: האקדמיה ללשון העברית. מוסד זה פועל מכוח חוק, אף על פי שהשפעתו בפועל מוגבלת. עיסוקו בעיקר בקביעת מונחים חדשים, כללי כתיב וכללי תחביר, המחייבים להלכה את מוסדות המדינה ואת מערכת החינוך הממלכתית. בפועל, חלק גדול מהחלטותיו אינו מתקיים. התפתחות המילונאות השימושית בישראל בשנות ה-90 יצרה מספר מילונים ומאגרי מידע המתעדים את הלשון העברית בפועל, ומשמשים אסמכתות חלופיות לכללי האקדמיה ללשון העברית 23 | 24 | לקראת תחילת תהליך החייאת השפה העברית, בעת שהיא שימשה רק כשפה שנייה בפי יהודים ושומרונים, היו לשפה שני ניבים - יהודי ושומרוני, כשהניב השומרוני היה על סף כליה גם כשפה שנייה, יחד עם העדה השומרונית עצמה. לניב היהודי היו שלוש דרכי הגיה עיקריות: אשכנזית, ספרדית ותימנית (יש המציינים גם הגייה עיראקית). עם החייאת השפה, בן-יהודה הכריז על ההגייה הספרדית כהגייה התקנית של העברית. אולם בפועל מחיי השפה דבקו בהגייה שהיא מעין פשרה בין הספרדית לאשכנזית וזו נשתרשה בעם. 25 | 26 | בשל התחייה המאוחרת של השפה העברית, אין כמעט ניבים אזוריים עבריים. למעשה, השפה הנשמעת בפי דוברים ילידיים זהה כמעט בכל חלקי ישראל. אפשר להבחין בשוני בין הניבים המדוברים בפי עדות יהודיות שונות (אתנולקטים). אולם, שוני זה מתבטא בעיקר בפונולוגיה, ולא בתחביר או במורפולוגיה. עיקרי שוני זה הם בהשפעה ספרדית-תימנית על ההגייה המקובלת ולעתים בהשפעה אשכנזית על ההגייה המקובלת (למשל בקרב חלק מהעדה החרדית בירושלים ובברוקלין). שוני מסוים בתחביר ובמורפולוגיה קיים בין ניבים מעמדיים של השפה (סוציולקטים), אולם שוני זה אינו גדול יחסית. 27 | 28 | ייחודה של העברית המודרנית הוא בכך שהיא משרתת במידה רבה אנשים ששפת אמם שונה. מספר הדוברים הלא-ילידיים משתווה פחות-או-יותר למספר הדוברים הילידיים, והיא אף משמשת לתקשורת בין קבוצות בתוך ישראל שאינן דוברות עברית (למשל, דיונים בכנסת, בבתי המשפט הישראליים וכיוצא בזה מתנהלים בעברית, גם כשכל המתדיינים שייכים לקבוצות שאינן דוברות עברית). כיוון שכך, העברית המודרנית חשופה להשפעה אינטנסיבית של שפות אחרות, כגון ערבית, רוסית, אנגלית ועוד, דבר המשנה אותה בהתמדה, ואף יוצר הבדלים בין קבוצות, אשר עשויים להתפתח לניבים של ממש. 29 | 30 | ביהודה ושומרון (וברצועת עזה בעת שנשלטה בידי ישראל) העברית היא שפת המינהל, בצד הערבית, המדוברת בקרב רוב האוכלוסייה המקומית. בניגוד לערביי ישראל, הלומדים עברית במערכת החינוך מגיל צעיר, ומנהלים את חייהם בשתי השפות במידה כמעט שווה, רוב דוברי הערבית בשטחים שולטים בעברית רק במידה חלקית או שאינם שולטים בה כלל. עם זאת, השפעת העברית על הערבית שבפיהם ניכרת מאוד, בעיקר עקב השימוש הרב במילים שאולות מן העברית. עם התגברות ההגירה של פועלים זרים לישראל נוצר "פידג'ין עברי", המשמש לתקשורת בין הפועלים לדוברי העברית הישראליים. 31 | 32 | 33 | לשפה העברית יש מורפולוגיה טיפוסית של שפה שמית. המאפיינים העיקריים הם ריבוי נטיות לכל מילה (בפרט לפעלים), נטייה לא-רציפה (כלומר בסיס המילה משתנה בנטייה, ולא רק המוספיות), ושינויים רבים בתנועות לעומת יציבות של העיצורים. מקובל לתאר יצירה של מילים בשפות שמיות, בכלל זה בשפה העברית, כתהליך של הרכבת שורש ומשקל. השורש הוא מורפמה, שהיא סדרה של 3–4 (לעתים נדירות: חמש או שש) אותיות; המשקל הוא סדרה דומה של תנועות ואלמנטים פרוזודיים (לפעמים נצמדות אליו גם מוספיות). באמצעות שילוב התנועות והאלמנטים הפרוזודיים בין עיצורי השורש נוצרת מילה. לדוגמה, הרכבת השורש כ-ת-ב על המשקל מִ-םְםָם יוצרת את המילה: מִכְתָב ("מִ" היא מוספית, לצורך תיאור המשקל מציינת כאן האות מ"ם סופית עיצור כלשהו). בדרך-כלל, למילים שנגזרות משורש אחד יש משמעות דומה, אולם יש לכך חריגים רבים. לשורשים ולמשקלים אין קיום בשפה כשלעצמם, אלא רק כמרכיב של מילים, ולעתים קרובות בצירוף מורפמות אחרות. אין הסכמה בין הבלשנים בדבר הממשות של השורש בשפה. יש הטוענים שמדובר בחלק בלתי נפרד מאוצר המילים של השפה, גם אם הוא מופיע רק בצירוף מורפמות אחרות, ואחרים טוענים שמדובר בהפשטה מדעית, שהדוברים אינם מודעים לה בצורה אינטואיטיבית. רוב הבלשנים מסכימים כי בעבר היו שורשים של שתי אותיות כגון "ב-א" ו"ק-מ" (כיום מקובל להתייחס לשורשים האלה כשורשים תלת-עיצוריים: ב-ו-א, ק-ו-מ). כמו כן, העברית המודרנית יוצרת שורשים של יותר מ-4 אותיות (בעיקר ממילים שאולות), כגון פלרטט, טלגרף. בעברית מודרנית נוצרות מילים ששורשן אינו ברור. למשל, מילים כמו "רמזור" או "מדרחוב" נוצרו בדרך של הֶלְחם בסיסים, כך שקשה לקבוע את שורשן. עם זאת, המילה "רמזור" התפתחה לשורש רמז"ר, כמו בביטוי "צומת מרומזר". כמו כן, הקשר הסמנטי בין מילים שנגזרו משורש אחד הוא לפעמים מעורפל. כך למשל, הפעלים "פסל" (במובן של פסילה) ו"פיסל" נראים כאילו נגזרו משורש אחד, אולם אין ביניהם קשר סמנטי, כיוון שהאחרון נגזר משורש של העברית המקראית, ואילו הראשון נגזר ממילה ארמית שנכנסה אל העברית בתקופה מאוחרת יותר. 34 | 35 | על פי המסורת היהודית, עשר המאמרות האלהיות שבהם נברא העולם היו בעברית, והמלאכים משתמשים בלשון זו. על כן השפה נקראת לשון הקודש. 36 | 37 | לפי ריה"ל בספרו "הכוזרי" (מאמר שני סעיף ס"ח) השפה העברית היא האצילה בשפות, והיא השפה שבה נגלה אלוהים לאדם וחוה (ולכן אדם נגזר מאדמה וחוה מחיים), אשר דיברו בשפה זו והנחילו אותם לבניהם ולאנושות כולה, שהשתמשה בה עד ימי מגדל בבל (דור הפלגה). אז התבלבלו הלשונות ונוצרו שפות רבות; אולם עֵבֶר המשיך גם אז להשתמש בעברית, ולכן נקרא בשם זה. מבלבול הלשונות נובע הדמיון של השפות הקדומות לעברית. 38 | 39 | הרמב"ם מציג נימוק שונה ופשוט יותר להיותה של העברית לשון הקודש. הוא מסביר זאת בכך שאין בשפה מילים מפורשות המתארות דברים הקשורים למין. המהר"ל חולק עליו (נתיב הצניעות, פרק ג') ואומר שהרמב"ם הפך את היוצרות, מכיוון שהשפה היא קדושה, ובה נברא העולם, לכן אין בה מילים המתארות מיניות ולא להפך. 40 | 41 | הגיית העברית עברה שינויים רבים במהלך אלפי שנות קיומה. במאה ה-19 שאפו מחדשי השפה העברית לאמץ את ההגייה הספרדית, בייחוד זו שהייתה נהוגה בקהילה הספרדית של ירושלים; זאת משום היוקרה שממנה נהנתה הקהילה הספרדית של ירושלים בעבר, ומשום שהגייתה הייתה קרובה למדי להגייה שמשתקפת בניקוד הטברני של המקרא. אלא שמרבית מחדשי השפה העברית ותומכיהם היו יהודים אשכנזים ממזרח אירופה, וההגייה העברית שהכירו הייתה שונה מאוד; על אף המאמץ להקנות לדיבור העברי החדש הגייה ספרדית, השפעת ההגייה האשכנזית והמבטא של שפת יידיש ניכר היטב בעברית המודרנית. 42 | 43 | כתב העברי מאופיין באלפבית המיוחד לו, הוא כולל 22 אותיות, וכן סימנים גרפיים נוספים (שהם פיתוחים מאוחרים יחסית), המשמשים בעיקר לציון תנועות. האלפבית המרובע המוכר היום הוא גרסה של הכתב הארמי "הבינלאומי" של הממלכה הפרסית, והוא החליף (לפי המסורת – על פי החלטה מגבוה של עזרא הסופר) את האלפבית העברי-פיניקי, המכונה גם "כתב דעץ/רעץ", שבו נעשה שימוש בממלכת יהודה, בממלכת ישראל וברחבי המזרח הקדום לפני גלות בבל במאה ה-6 לפנה"ס. האלפבית העברי-פיניקי לא נעלם כליל, והוא המשיך לשמש את השומרונים (במידת-מה עד היום: כתב העת של השומרונים מודפס בחלקו באלפבית זה). בתקופת הבית השני כמו גם בהמשך, בזמן מרד בר כוכבא, נשאו מטבעות היהודים כתובות בכתב זה. כתב זה מופיע גם כיום על חלק מהמטבעות שמונפקים על ידי מדינת ישראל, למשל על מטבעות של שקל חדש ושל עשרה שקלים, ופה-ושם ניתן למצוא אותו במקומות נוספים (למשל: על סמל העיר נהריה). על הכתב העברי הקדום ראה בהרחבה בערכו. 44 | 45 | צד הכתב המודפס, הוא הכתב המרובע, קיים בעברית גם כתב עברי רהוט, המשמש לכתיבה מהירה. כתב זה מתאפיין בקווים מעוגלים, והוא נפוץ מאוד בכתבי יד לא-מודפסים. מקורו של כתב זה בקהילות יהודיות אשכנזיות באירופה. סוג אחר של כתב רהוט, מכונה כתב רש"י ומקורו בקהילות היהודיות הספרדיות. כינויו נובע מן העובדה שהספר הראשון שהודפס בכתב זה היה במקרה פירושו של רש"י. ניסיונות אחדים להשתמש בכתב הזה גם בהדפסת טקסטים יומיומיים לא עלו יפה. עד היום פרשנות רש"י ופרשנויות נוספות על התנ"ך והתלמוד נדפסות ונלמדות בכתב זה. יחד עם זאת ניתן לזהות מעבר לכתב המרובע בטקסטים שמיועדים להיות נגישים גם לקוראים שלא הורגלו לקריאה אינטנסיבית בכתב רש"י. 46 | 47 | בספרי תנ"ך, ספרי שירה וספרים לילדים מקובל לסמן את התנועות באמצעות ניקוד. סימני הניקוד המקובלים כיום, אשר מופיעים מתחת לאותיות, מעליהן ובתוכן, הומצאו בטבריה במאה ה-7, ושימשו במקור כאמצעי עזר לקריאת התנ"ך (בעבר התקיימו גם סוגי ניקוד עברי נוספים). חכמי טבריה הוסיפו גם סימנים לטעמי המקרא; סימנים אלה משמשים כסימני פיסוק וכסימנים לאופן הנגינה שבה יש לקרוא את פסוקי התנ"ך. הטעמים מודפסים כיום רק בספרי תנ"ך. בכל טקסט אחר נעשה שימוש בסימני פיסוק שהתפתחו באירופה ומשמשים בכתיבת רוב השפות בעולם. --------------------------------------------------------------------------------