Ansatz zur Verarbeitung eines online generierten CSV Files

  • 9 Antworten
  • Letztes Antwortdatum
Tiefkuehlpizza

Tiefkuehlpizza

Neues Mitglied
7
Habt ihr ein Tipp?

Die Url beispiel.de/kalender.php?a=export&export=csv&year=2022 generiert ein CSV zum Download.
Ich würde den Inhalt des Files gerne in meiner App verwerten (Abspeichern muss nicht sein).

Momentaner Ansatz in Kotlin:
Code:
...
val CSV_File_Path = "https://www.beispiel.de/kalender.php?a=export&export=csv&year=2022
val myUri: Uri = Uri.parse(CSV_File_Path)
val inputStream: InputStream? = ...appContext()...contentResolver.openInputStream(myUri)
...

Ich werde rausgeworfen mit:
...FileNotFoundException...

Passt der Ansatz um ein generiertes File downzuloaden?
In welche Richtung muss ich meinen Ansatz anpassen?

Viele Grüße
Pizza
 
Zuletzt bearbeitet:
Danke für das Feedback.

Ich habe es mit OkHTTP3 wie folgt probiert:
Code:
...

val client = OkHttpClient()

val request = Request.Builder()
    .url("https://publicobject.com/helloworld.txt")
    .build()

client.newCall(request).execute().use { response ->
    if (!response.isSuccessful) throw IOException("Unexpected code $response")
    var strng = response.toString()
}
...

Absturz beim erstellen vom Request.
Code:
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: playground, PID: 14707
    android.os.NetworkOnMainThreadException
        at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1605)
        at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:115)
        at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:103)
        at java.net.InetAddress.getAllByName(InetAddress.java:1152)
        at okhttp3.Dns$1.lookup(Dns.java:40)
        at okhttp3.internal.connection.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:185)
        at okhttp3.internal.connection.RouteSelector.nextProxy(RouteSelector.java:149)
        at okhttp3.internal.connection.RouteSelector.next(RouteSelector.java:84)
        at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:214)
        at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
        at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
        at okhttp3.RealCall.execute(RealCall.java:92)
        at playground.networking.NetworkManager$getSiteAuthed$1.invoke(NetworkManager.kt:263)
        at playground.networking.NetworkManager$getSiteAuthed$1.invoke(NetworkManager.kt:49)
        at playground.networking.TokenManager$authenticate$1.invoke(TokenManager.kt:47)
        at playground.networking.TokenManager$authenticate$1.invoke(TokenManager.kt:36)
        at playground.networking.TokenManager.getToken(TokenManager.kt:82)
        at playground.networking.TokenManager.authenticate(TokenManager.kt:46)
        at playground.networking.NetworkManager.getSiteAuthed(NetworkManager.kt:190)
        at playground.networking.NetworkManager.getSiteAuthed$default(NetworkManager.kt:186)
        at playground.networking.Clndr.fetch(Calendar.kt:24)
        at playground.networking.NetworkManager$indexAll$1.invoke(NetworkManager.kt:643)
        at playground.networking.NetworkManager$indexAll$1.invoke(NetworkManager.kt:49)
        at playground.networking.NetworkManager$indexAll$onDone$1.invoke(NetworkManager.kt:576)
        at playground.networking.NetworkManager$indexAll$onDone$1.invoke(NetworkManager.kt:49)
        at playground.networking.Courses$createIndex$onDone$1.invoke(Courses.kt:55)
        at playground.networking.Courses$createIndex$onDone$1.invoke(Courses.kt:16)
        at playground.networking.Courses$createIndex$2$3.invoke(Courses.kt:118)
        at playground.networking.Courses$createIndex$2$3.invoke(Courses.kt:16)
        at playground.networking.NetworkManager$getSiteAuthed$1$2.onResponse(NetworkManager.kt:308)
        at com.androidnetworking.common.ANRequest.deliverSuccessResponse(ANRequest.java:731)
        at com.androidnetworking.common.ANRequest.access$6500(ANRequest.java:80)
        at com.androidnetworking.common.ANRequest$6.run(ANRequest.java:709)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

Gleiches Verhalten bei Nutzung von InputStream, OpenCsv und ApacheCsv.
Internet Permission ist beachtet.
Das einlesen lokaler Files (Im App Verzeichnis auf dem Emulator) funktioniert.

Ich versuche morgen noch ein neues Projekt zu erstellen und nur das dort reinzuklöppeln.
Bei dem Versuch beachte ich dann alle Details aus @swa00 Beispiel.
Hätte trotzdem gedacht, dass es "schnell" funktioniert.

Über Tipps würde ich mich freuen.

Gruß
Pizza
 
Hast du auch die Internet pemission im manifest gesetz?

<uses-permission android:name="android.permission.INTERNET" /> <application ...
 
Ja, die Internet Permission ist gesetzt 👍
 
Also irgendwas stimmt mit deinen Policies nicht

at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1605)

setze mal zur Probe das im Application-Block der manifest ein
android:usesCleartextTraffic="true"

P.S Requests müssen wie deinem ersten Beispiel im Thread laufen
 
Hallo Zusammen,

also auf den Tipp von @swa00 hin habe ich mal nach der zitierten Fehlermeldung gegoogelt.
Soweit ich das verstanden habe, sind aufwandsintensive Funktionen nicht im Main Thread erlaubt.

Dann habe ich die Funktion in eine eigene Klasse verlegt und dort run() überschrieben.
Immer noch der Fehler.

Dann habe ich mich in async eingelesen und das darüber gemacht und nun funktioniert es.

Code:
class RqstRun(private val scope: CoroutineScope, private val url: String = ""): Runnable {

    // Create OkHttp Client
    val client = OkHttpClient.Builder()
            .addNetworkInterceptor { chain ->
                chain.proceed(
                    chain.request()
                        .newBuilder()
                        .header("User-Agent", "milkalilalaunebaer")
                        .build()
                )
            }
            .build()

    override fun run() {
        fetch()
    }

    private fun fetch() = scope.async {
        try {
            // Create URL
            val myUrl = URL(url)
            // Build request
            val request = Request.Builder().url(myUrl).build()
            // Execute request
            val response = client.newCall(request).execute()

            val str = response.body!!.string()
            //Juhuu - Inhalt ist drin
        }
        catch(err:Error) {
            print("Error when executing get request: "+err.localizedMessage)
        }
    }
}

In main:
Code:
val myRqstRun = RqstRun(GlobalScope, sUrl)
            myRqstRun.run()

Danke für die Hilfe.

Gruß
Pizza
Beiträge automatisch zusammengeführt:

Wie ist das eigentlich, wenn ich mich vorher erst anmelden muss?

Die App an der ich ein bissel bastele macht das schon, ich habe dann ein valides Token und andere "normale" Seiten, die hinter der Anmeldeschranke sind, bekomme ich damit.

Das Token ist an der Stelle mit dem OkHTTP3 Request auch gültig
Bei der Seite bekomme ich allerdings nur das Fehlerfeedback statt den CSV Export.

Pseudocode
Code:
...

Token Check

if (success) {
   if(meine spezielle Seite)
    OkHTTP3  Zeugs ////Fehler - Du bist nicht angemeldet Seite

   else
     Parsing normal sites //OK
}

...

Muss man beim OkHTTP3 Request was Spezielles beachten?
Stichwort zum weiterlesen?

Gruß
Pizza
Beiträge automatisch zusammengeführt:

Update RequestBuilder - Hilft aber auch nicht weiter.
Code:
var tkn = prefs.getString("token", "")!!

val request = Request.Builder()
     .url(myUrl)
     .header("Authorization", tkn)
     .build()

Gruß
Pizza
 
Zuletzt bearbeitet:
Mittlerweile bekomme ich das *.csv File.

Jetzt möchte ich den Inhalt Datensatz für Datensatz verarbeiten.
Dazu möchte ich den Fileinhalt splitten.
Mein Problem ist, dass manche Datensätze über mehrere Zeilen gehen.
Ich benötige ein Suchmuster, welches Folgendes findet:
Code:
"beliebige Zeichen ohne ; aber mit potentiellen Zeilenumbrüchen" + ";" {8 mal} + "beliebige Zeichen ohne ;" + Zeilenumbruch [\r\n]

Ich hab's mit Regex probiert, aber ich habe gerade irgendwie einen gordischen Knoten im Kopf.
Für mich ist das next Level...
Hat jemand das Schwert um den Knoten zu lösen?

Beispiel (bei xxx beginnt ein neuer Datensatz):
Code:
Titel;Art;Von_Datum;Von_Uhrzeit;Bis_Datum;Bis_Uhrzeit;Beschreibung;Ort;Verantwortlich XXX
Klassenlehrerunterricht der 5. Klassen + 7H;Zur Info/ Sonstiges;30.08.2021;00:00;03.09.2021;23:59;2. bis 5. Stunde (Einschulung der 5. Jgst. am 31.08.21);; XXX
Beginn des neuen Schuljahres;Zur Info/ Sonstiges;30.08.2021;08:30;30.08.2021;13:00;"1. Stunde: unterrichtsfrei
2. Stunde:
•    8.30 Uhr. Die Schülerinnen und Schüler der 6. u. 7. Jgst. finden sich an den bereits bekannten Standorten ein
•    8.45 Uhr: Die Schülerinnen und Schüler der 8. Jgst. finden sich an den bereits bekannten Standorten ein
•    9.00 Uhr: Die Schülerinnen und Schüler der 9. u. 10. Jgst. finden sich an den bereits bekannten Standorten ein
- 3. u. 4.Stunde: Unterricht bei der Klassenlehrkraft
- 5. u. 6. Stunde: Unterricht nach Plan
- ab 7. Stunde: unterrichtsfrei
";; XXX
Einschulungsfeier 5. Jahrgangsstufe;Zur Info/ Sonstiges;31.08.2021;09:00;31.08.2021;13:00;(Ablauf: siehe individueller Plan);; XXX
AGs: dreiwöchige Schnupperphase;Zur Info/ Sonstiges;06.09.2021;00:00;06.09.2021;23:59;;; XXX
Frist: Abgabe der WP-Zettel;Zur Info/ Sonstiges;08.09.2021;00:00;08.09.2021;23:59;;; XXX

Danke und Gruß
Pizza
 
Ich hab's gefunden - glaube ich
Code:
([^;]*[;]){8}([^;]*)([\r\n]+)
 
Zurück
Oben Unten