Je veux lire un tas de fichiers texte depuis un emplacement hdfs et effectuer un mappage dessus en une itération à l'aide de spark.
JavaRDD<String> records = ctx.textFile(args[1], 1);
est capable de lire un seul fichier à la fois.
Je veux lire plus d'un fichier et les traiter comme un seul RDD. Comment?
Vous pouvez spécifier des répertoires entiers, utiliser des caractères génériques et même des fichiers CSV de répertoires et de caractères génériques. Par exemple.:
sc.textFile("/my/dir1,/my/paths/part-00[0-5]*,/another/dir,/a/specific/file")
Comme Nick Chammas le fait remarquer, ceci est une exposition de FileInputFormat
de Hadoop et cela fonctionne donc également avec Hadoop (et Scalding).
Utilisez union
comme suit:
val sc = new SparkContext(...)
val r1 = sc.textFile("xxx1")
val r2 = sc.textFile("xxx2")
...
val rdds = Seq(r1, r2, ...)
val bigRdd = sc.union(rdds)
Alors la bigRdd
est le RDD avec tous les fichiers.
Vous pouvez utiliser un seul appel textFile pour lire plusieurs fichiers. Scala:
sc.textFile(','.join(files))
Vous pouvez utiliser ceci
Vous pouvez d’abord obtenir un tampon/une liste de chemins S3:
import scala.collection.JavaConverters._
import Java.util.ArrayList
import com.amazonaws.services.s3.AmazonS3Client
import com.amazonaws.services.s3.model.ObjectListing
import com.amazonaws.services.s3.model.S3ObjectSummary
import com.amazonaws.services.s3.model.ListObjectsRequest
def listFiles(s3_bucket:String, base_prefix : String) = {
var files = new ArrayList[String]
//S3 Client and List Object Request
var s3Client = new AmazonS3Client();
var objectListing: ObjectListing = null;
var listObjectsRequest = new ListObjectsRequest();
//Your S3 Bucket
listObjectsRequest.setBucketName(s3_bucket)
//Your Folder path or Prefix
listObjectsRequest.setPrefix(base_prefix)
//Adding s3:// to the paths and adding to a list
do {
objectListing = s3Client.listObjects(listObjectsRequest);
for (objectSummary <- objectListing.getObjectSummaries().asScala) {
files.add("s3://" + s3_bucket + "/" + objectSummary.getKey());
}
listObjectsRequest.setMarker(objectListing.getNextMarker());
} while (objectListing.isTruncated());
//Removing Base Directory Name
files.remove(0)
//Creating a Scala List for same
files.asScala
}
Maintenant, passez cet objet List au code suivant, remarque: sc est un objet de SQLContext
var df: DataFrame = null;
for (file <- files) {
val fileDf= sc.textFile(file)
if (df!= null) {
df= df.unionAll(fileDf)
} else {
df= fileDf
}
}
Maintenant, vous avez un dernier RDD unifié, à savoir df
Facultatif, et vous pouvez également le repartitionner dans un seul BigRDD
val files = sc.textFile(filename, 1).repartition(1)
Le repartitionnement fonctionne toujours: D
vous pouvez utiliser
JavaRDD<String , String> records = sc.wholeTextFiles("path of your directory")
ici, vous obtiendrez le chemin de votre fichier et le contenu de ce fichier. afin que vous puissiez effectuer toute action d'un fichier entier à un moment qui enregistre les frais généraux
Toutes les réponses sont correctes avec sc.textFile
Je me demandais pourquoi pas wholeTextFiles
Par exemple, dans ce cas ...
val minPartitions = 2
val path = "/pathtohdfs"
sc.wholeTextFiles(path,minPartitions)
.flatMap{case (path, text)
...
une des limites est que nous devons charger de petits fichiers, sans quoi les performances seront mauvaises et risquent d’entraîner un MOO.
Remarque :
Référence supplémentaire à visiter
Il existe une solution propre simple disponible. Utilisez la méthode wholeTextFiles (). Cela prendra un répertoire et forme une paire clé-valeur. Le RDD retourné sera une paire RDD. Retrouvez ci-dessous la description de Spark docs :
SparkContext.wholeTextFiles vous permet de lire un répertoire contenant plusieurs petits fichiers texte et les renvoie sous forme de paires (nom de fichier, contenu). Ceci est en contraste avec textFile, qui renverrait un enregistrement par ligne dans chaque fichier
TRY THIS Interface utilisée pour écrire un DataFrame sur des systèmes de stockage externes (tels que des systèmes de fichiers, des magasins de valeurs-clés, etc.). Utilisez DataFrame.write () pour y accéder.
Nouveau dans la version 1.4.
csv (chemin d'accès, mode = None, compression = None, sep = None, quote = None, escape = None, en-tête = None, nullValue = None, escapeQuotes = None, quoteAll = None, dateFormat = None, timestampFormat = None). .Enregistre le contenu du DataFrame au format CSV dans le chemin spécifié.
Paramètres: Path - chemin de tout système de fichiers pris en charge par Hadoop Mode – Spécifie le comportement de l'opération de sauvegarde lorsque des données existent déjà.
append: ajoute le contenu de ce DataFrame à des données existantes . écrase: écrase des données existantes .. ignore: ignore cette opération si les données existent déjà . erreur (cas par défaut): déclenche une exception si les données existent déjà . compression - codec de compression à utiliser lors de la sauvegarde dans un fichier. Cela peut être l’un des noms abrégés connus et insensibles à la casse (aucun, bzip2, gzip, lz4, snappy et deflate) . Sep - définit le caractère unique comme séparateur pour chaque champ et valeur. Si aucun est défini, il utilise la valeur par défaut, . Quote - définit le caractère unique utilisé pour échapper les valeurs entre guillemets où le séparateur peut faire partie de la valeur. Si la valeur par défaut est Aucun, il utilise la valeur par défaut, ". Si vous souhaitez désactiver les devis, vous devez définir une chaîne vide . Escape - définit le seul caractère utilisé pour échapper les guillemets dans une valeur déjà citée. Si Aucune n'est définie, elle utilise la valeur par défaut,\ EscapeQuotes - Indique si les valeurs contenant des guillemets doivent toujours être placées entre guillemets. Si aucune est définie, elle utilise la valeur par défaut, true, en échappant à toutes les valeurs contenant un caractère de guillemet. quoteAll - Indicateur signalant si toutes les valeurs doivent toujours être placées entre guillemets. Si la valeur est définie sur None, la valeur par défaut est false, mais uniquement les valeurs d'échappement contenant un caractère de citation header - écrit les noms des colonnes sous la forme Première ligne. Si aucun est défini, il utilise la valeur par défaut, false . nullValue - définit la représentation sous forme de chaîne d'une valeur null. Si aucun est défini, il utilise la valeur par défaut, chaîne vide . dateFormat - définit la chaîne qui indique un format de date.Les formats de date personnalisés suivent les formats de Ja va.text.SimpleDateFormat. Ceci s'applique au type de date. Si aucun n'est défini, il utilise la valeur par défaut, aaaa-MM-jj . TimestampFormat - définit la chaîne qui indique un format d'horodatage. Les formats de date personnalisés suivent les formats disponibles sur Java.text.SimpleDateFormat. Ceci s'applique au type d'horodatage. Si aucun n'est défini, il utilise la valeur par défaut, aaaa-MM-jj'T'HH: mm: ss.SSSZZ.